题目
输入: [[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] 可被视为重叠区间。
分析
首先根据所给用例,找出解题关系。
1.因为题目给的序列不一定有序的,所以我们需要先将序列排序,左边界按照升序排序,左边界如果相等,
右边界按照降序排列。
2.排好序后,创建一个二维数组来保存结果,直接在原数组上操作比较麻烦,考虑的情况较多,具体可以
看下面注释的例子。注意先把第一个插入到保存结果的二维数组里面。否则直接从第一个开始,会多算
一个。
首先判断前一个区间的右边界是否大于下一个区间左边界,如果大于,说明两个区间有交集,需要更改,然后
在判断前区间的右边界是否小于等于后区间的右边界,根据结果判断如何修改。如果大于,则跳过进行下一个
,不需要修改res。然后再将res的和下一个比,这样的好处就是不用动原数组,减少一些逻辑和操作。
3.如果不存在交集,则需要往res里面添加,同时记住cnt也需要++。
附注:
1.这种看起来和序列有关的,并且确实需要比较大小的,可以考虑先排序
2.将题目所给数列排序,将左边界从小到大排列,也有好处,就是这样我们可以只比较右边界,复杂度降低,
同时减少解题时遗漏。
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
class MyClass
{
public:
static bool cmp(const vector<int>& a,const vector<int> & b){
if (a[0] == b[0])
{
return a[1] > b[1];
}
else
{
return a[0] < b[0];
}
}
vector<vector<int>> merge(vector<vector<int>>& intervals){
if (intervals.empty()){
return intervals;
}
vector<vector<int>> res;
int cnt = 0;
sort(intervals.begin(), intervals.end(), cmp);
vector<int> tmp;
tmp.push_back(intervals[0][0]);
tmp.push_back(intervals[0][1]);
res.push_back(tmp);
for (int i = 1; i < intervals.size(); ++i){
if (res[cnt][1] >= intervals[i][0]){
if (res[cnt][1] <= intervals[i][1]){
res[cnt][1] = intervals[i][1];
}
}
else
{
++cnt;
res.push_back(intervals[i]);
}
}
return res;
}
};