题目: 56. 合并区间 - 力扣(LeetCode) (leetcode-cn.com)
思路一:排序+容器
分析:
先按左端点进行排序,然后比较当前区间的左端点和前一个区间的右端点进行比较,如果当前区间的左端点比前一个区间的大,则没有重合,如果比之小,就会重合
步骤:
- 定义一个二维数组,存放结果
- 对数组按照左端点进行升序排列
- 遍历数组元素
- 如果是第一个元素,则加入结果数组,如果不是首个元素,让当前区间的左端点和结果数组里面的最后一个元素的右端点进行比较,如果比之大,就加入结果元素,反之,则就是重合,就比较当前节点的右端点和结果数组元素的右端点的大小,比之大,就将结果数组的最后一个元素的右端点改成当前区间的右端点。
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>>result;
int len=intervals.size();
sort(intervals.begin(),intervals.end()); //排序
for(int i=0;i<len;i++)
{
if(result.empty()) //首元素入结果数组
result.push_back(intervals[i]);
else if(intervals[i][0]<=result[result.size()-1][1]) //比较当前区间的左端点和数组最后一个元素的右端点
{
if(intervals[i][1]>result[result.size()-1][1])
result[result.size()-1][1]=intervals[i][1];
}
else if(intervals[i][0]>result[result.size()-1][1])
{
result.push_back(intervals[i]);
}
else
{
continue;
}
}
return result;
}
优化:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if (intervals.size() == 0) {
return {};
}
sort(intervals.begin(), intervals.end());
vector<vector<int>> merged;
for (int i = 0; i < intervals.size(); ++i) {
int L = intervals[i][0], R = intervals[i][1];
if (!merged.size() || merged.back()[1] < L) { //首元素入结果数组 当前区间的左端点大于数组最后一个元素的右端点
merged.push_back({L, R});
}
else {
merged.back()[1] = max(merged.back()[1], R);
}
}
return merged;
}
思路二:排序+双指针
步骤:
-
对 vector<vector> 排序,需要按照先比较区间开始,如果相同再比较区间结束,使用默认的排序规则即可
-
使用双指针,左指针指向当前区间的开始
-
使用一个变量来记录连续的范围
-
右指针开始往后寻找,如果后续区间的开始至比t还小,说明重复了,可以归并到一起,
-
此时更新t到更大的值
-
直到区间段楷,将t作为区间结束,存储到答案里面‘
-
然后移动左指针,跳过已经合并的区间。
注意:左指针指向区间的开始,右指针指向区间的结束。这就是左右指针的运用
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>>result;
int len=intervals.size();
sort(intervals.begin(),intervals.end()); //排序
for(int i=0;i<len;i++)
{
int t=intervals[i][1];
int j=i+1;
while(j<intervals.size()&&intervals[j][0]<=t)
{
t=max(intervals[j][1],t);
j++;
}
result.push_back({intervals[i][0],t});
i=j-1;
}
return result;
}