Merge Intervals 合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

思路:按照之前贪心算法的惯性思想,我首先对end进行排序,然后按照如果有区间重叠就合并区间的解法,但是栽在了这个case下:[[2,3],[4,5],[6,7],[8,9],[1,10]]  我的输出是:[[2,3],[4,5],[6,7],[1,10]] 只对最后两个区间进行了合并,这显然是不对的。但是如果稍微翻转下思想,如果对start进行排序,就可以解决问题(待会儿给出证明)。这里先说解法:

首先对start进行排序,用last记录上一次最宽的区间,如果当前区间intervals[i]的start大于last的end,那么意味着这是一段新的区间,我们把last加到res中,否则这段区间和前面的区间有重叠可以合并,所以合并到前面的区间。当遍历完数组后我们考察res的最后一个区间的end是否小于last的end,如果是就把last加到res中,这是因为假如我们遍历到最后一个区间做的还是合并操作,那么这个区间就会被遗漏而没有加到res中,所以要补加到结果中。

证明:(不想看证明的可以直接跳过)

假如按照我们的解法存在3个区间i,j,k可以合并(满足按照时间顺序i<j<k),即区间i和j不能合并,区间j和k不能合并,i和k可以合并(就是上文中出现的test case)。根据条件可以得出几条结论:

i.start<i.end

j.start<j.end   且i和j不能合并,所以i.end<j.start

k.start<k.end   且j和k不能合并,所以j.end<k.start

因为i和k可以合并,所以i.end>=k.start,我们要证明不会出现这种情况。

根据上面的不等式:i.end<j.start<j.end<k.start和要证明的i.end>=k.start相悖,所以不可能出现这种情况。

参考代码:

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
static bool intervalsCmp(const Interval &a, const Interval &b) {
	return a.start < b.start;
}
vector<Interval> merge(vector<Interval>& intervals) {
	if (intervals.size() == 0) return {};
	sort(intervals.begin(), intervals.end(), intervalsCmp);
	vector<Interval> res;
	Interval last = intervals[0];
	for (int i = 1; i < intervals.size(); i++) {
		if (intervals[i].start <= last.end) {
			last.end = max(last.end, intervals[i].end);
		}
		else {
			res.push_back(last);
			last = intervals[i];
		}
	}
	if (res.empty() || res.back().end < last.start) {
		res.push_back(last);
	}
	return res;
}
};

猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/82421130
今日推荐