题目描述
原题链接:56. 合并区间
解题思路
局部最优解: 按区间左边界从小到大排列,合并时候按最大右边界合并。
全局最优解: 合并所有有重叠的区间。
(1)合并重叠区间,对最后一个单独处理
先按左边界从小打到排序,每次前后两个区间对比,无重叠则将前面的区间加入结果集,有重叠则将两个区间合并。对最后一个区间大度处理。
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if(intervals.size() == 1) return intervals;
sort(intervals.begin(), intervals.end(), cmp);
vector<vector<int>> res;
int n = intervals.size();
for(int i = 1; i < n; i++) {
if(intervals[i - 1][1] < intervals[i][0]) { // 无重叠,将前面的加入
res.push_back(intervals[i - 1]);
} else { // 有重叠,将前面的合并
intervals[i][0] = intervals[i - 1][0];
intervals[i][1] = max(intervals[i][1], intervals[i - 1][1]);
}
}
// 对最后一个区间处理
if(intervals[n - 2][1] >= intervals[n - 1][0]) { // 有重叠,则合并
intervals[n - 1][0] = intervals[n - 2][0];
intervals[n - 1][1] = max(intervals[n - 1][1] ,intervals[n - 2][1]);
}
res.push_back(intervals[n - 1]);
return res;
}
};
(2)双指针方法
设置一个左边界和右边界指针,从第一个开始和后一个对比,若重叠则合并,若不重叠则直接加入。
class Solution {
public:
static bool cmp(const vector<int>& a, const vector<int>& b) {
return a[0] < b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if(intervals.size() == 1) return intervals;
sort(intervals.begin(), intervals.end(), cmp);
vector<vector<int>> res;
int n = intervals.size();
for(int i = 0; i < n; i++) { // 注这个外面的for对比到n,里面的对比到n - 1,可以让最后一个一块都合并
int l = intervals[i][0], r = intervals[i][1]; // 获取第一个的左边界和右边界
while(i < n - 1 && r >= intervals[i + 1][0]) { // 第一个的右边界和第二个的左边界进行对比
r = max(r, intervals[i + 1][1]); // 若有重叠,则合并
i++;
}
res.push_back({l, r});
}
return res;
}
};
Python
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
n = len(intervals)
if n == 1:
return intervals
res = []
intervals.sort(key=lambda x:x[0])
for i in range(n):
l, r = intervals[i][0], intervals[i][1]
if res and res[-1][1] >= l:
res[-1][1] = max(res[-1][1], r)
else:
res.append([l, r])
return res
参考文章:【合并区间】排序 + 双指针、56. 合并区间