一、题目
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
二、排序解法
我们用数组 merged 存储最终的答案。
首先,我们将列表中的区间按照左端点升序排序。然后我们将第一个区间加入 merged 数组中,并按顺序依次考虑之后的每个区间:
如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,我们可以直接将这个区间加入数组 merged 的末尾;
否则,它们重合,我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。
class Solution {
public:
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}); // 如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合
}
else { // 否则,它们重合,我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。
merged.back()[1] = max(merged.back()[1], R);
}
}
return merged;
}
};
三、双指针解法
对 vector<vector<int>> 排序,需要按照先比较区间开始,如果相同再比较区间结束,使用默认的排序规则即可
- 使用双指针,左边指针指向当前区间的开始
- 使用一个变量来记录连续的范围 t
- 右指针开始往后寻找,如果后续的区间的开始值比 t 还小,说明重复了,可以归并到一起
- 此时更新更大的结束值到 t
- 直到区间断开,将 t 作为区间结束,存储到答案里
- 然后移动左指针,跳过中间已经合并的区间
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(),intervals.end());
vector<vector<int>> ans;
for (int left = 0; left < intervals.size();) { // 左指针
int temp = intervals[left][1]; // 右边界
int right = left + 1; // 右指针
while (right < intervals.size() && intervals[right][0] <= temp) { // 有重合
temp = max(temp, intervals[right][1]);
right++;
}
ans.push_back({intervals[left][0], temp});
left = right;
}
return ans;
}
};
参考: