目录
题目链接
题目描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
方法一
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> ans;
sort(intervals.begin(), intervals.end()); //将各行按首元素排序
int left, right; //表示区间的左边界和右边界
for (int i = 0; i < intervals.size(); i++)
{
left = intervals[i][0];
right = intervals[i][1];
int j;
for (j = i + 1; j < intervals.size(); j++)
//在该循环中寻找是否有能够合并的区间
{
if (right < intervals[j][0])
//如果目前的右边界小于该区间的左边界,说明合并不了,退出
{
j--;
break;
}
if (right >= intervals[j][1] && j+1<intervals.size())
//如果目前的右边界大于等于该区间的右边界,说明该区间包含于[left,right]中,继续判断下一个区间(如果存在)
{
continue;
}
if (right >= intervals[j][0] && right < intervals[j][1])
//如果目前的右边界大于等于该区间的左边界,但小于其右边界,合并
{
right = intervals[j][1];
}
}
i = j; //跳过已经判断完的区间
ans.push_back({ left , right });
}
return ans;
}
};
其中sort函数作用于二维数组vector的效果是,将vector各行按照首元素从小到大排序。
虽然该方法使用了两层的for循环,但实际上数组intervals中的各个区间只遍历了一次,由于使用了sort函数,时间复杂度为O(nlogn)。
方法二
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> ans;
sort(intervals.begin(), intervals.end()); //将各行按首元素排序
int left, right; //表示区间的左边界和右边界
for (int i = 0; i < intervals.size(); i++)
{
left = intervals[i][0];
right = intervals[i][1];
if (!ans.size() || ans.back()[1] < left)
//如果该区间的左边界比ans中最后一个区间的右边界还大,则插入该区间
{
ans.push_back({ left , right });
}
else
//否则,合并两个区间,即选择一个最大的右边界作为ans中最后一个区间的右边界
{
ans.back()[1] = max( ans.back()[1] , right );
}
}
return ans;
}
};
官方的题解看起来还是赏心悦目!虽然和我的方法在复杂度上是一样的,但是代码却更加简洁明了,省去了方法一中较繁琐的条件判断。
方法三
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
vector<vector<int>> ans;
//left和right表示在正在合并的区间的左右边界
int left = intervals[0][0], right = intervals[0][1];
for (int i = 1; i < intervals.size(); i++)
{
int curleft = intervals[i][0], curright = intervals[i][1];
//如果当前这个区间的左边界位于正在合并的区间的左右边界内,则选出right和curright中的最大值作为新的右边界
if (left <= curleft && curleft <= right) right = max(right, curright);
//否则说明当前的这个区间已经无法合并到区间[left,right]中了
else
{
ans.push_back({left, right}); //将区间[left,right]加入ans中
//重新开始下一轮判断
left = curleft;
right = curright;
}
}
ans.push_back({left, right}); //别忘了最后一个区间
return ans;
}
};