《代码随想录》Ⅷ 贪心算法 56. 合并区间
革命尚未成功,同志仍需努力!
题目:力扣链接
- 以数组 intervals 表示若干个区间的集合,其中单个区间为
intervals[i] = [starti, endi]。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
一、思想
这道题的核心是使用贪心算法解决区间合并问题,具体思路如下:
-
区间排序:首先将所有区间按照起始位置进行排序
-
顺序合并:依次处理每个区间,与结果集中的最后一个区间比较
-
重叠处理:
- 如果当前区间与结果集最后一个区间重叠,则合并这两个区间
- 否则直接将当前区间加入结果集
-
边界更新:合并时取两个区间结束位置的较大值作为新区间的结束
二、代码
/*
* 解题思路:
* 1. 首先对区间按照起始位置进行排序
* 2. 遍历排序后的区间,合并重叠区间
* 3. 维护一个结果数组,动态更新合并后的区间
*/
class Solution
{
public:
// 自定义比较函数,用于区间排序
static bool cmp(const vector<int> &a, const vector<int> &b)
{
if (a[0] == b[0]) { // 如果起始位置相同
return a[1] > b[1]; // 按结束位置降序排列
}
return a[0] < b[0]; // 默认按起始位置升序排列
}
vector<vector<int>> merge(vector<vector<int>> &intervals)
{
vector<vector<int>> result; // 存储合并后的结果
if (intervals.size() == 0) { // 处理空输入
return result;
}
// 第一步:对区间进行排序
sort(intervals.begin(), intervals.end(), cmp);
// 将第一个区间加入结果集
result.push_back(intervals[0]);
// 第二步:遍历并合并重叠区间
for (int i = 1; i < intervals.size(); ++i) {
if (result.back()[1] >= intervals[i][0]) { // 如果当前区间与结果集最后一个区间重叠
// 合并区间,取最大的结束位置
result.back()[1] = max(result.back()[1], intervals[i][1]);
}
else { // 不重叠则直接加入结果集
result.push_back(intervals[i]);
}
}
return result;
}
};
三、代码解析
1. 算法工作原理分解
1.1 排序阶段
-
目的:使所有区间按起始位置有序排列
-
关键点:使用自定义比较函数
cmp -
排序规则:
- 主排序键:区间起始位置升序
- 次排序键:区间结束位置降序(相同起始位置时)
1.2 初始化阶段
- 结果集:初始化为空
- 边界处理:直接处理空输入情况
1.3 合并阶段
-
重叠判断:
result.back()[1] >= intervals[i][0] -
合并操作:
- 保留原起始位置
- 更新结束位置为
max(原结束, 当前结束)
-
非重叠处理:直接加入结果集
2. 关键点说明
-
贪心策略:每次处理都保证结果集最后一个区间是最新的可合并区间
-
排序重要性:确保后续只需线性扫描即可完成合并
-
边界情况:
- 完全包含的区间会自动合并
- 相邻区间(start_i == end_j)也会合并
四、复杂度分析
-
时间复杂度:
O(n log n)- 排序阶段:
O(n log n)(快速排序) - 合并阶段:
O(n)(单次线性扫描) - 总体以排序操作为主导
- 排序阶段:
-
空间复杂度:
O(n)- 结果存储:最坏情况下需要存储所有原始区间
- 排序栈空间:
O(log n) - 不计输入输出空间则为
O(1)
白展堂:人生就是这样,苦和累你总得选一样吧?哪有什么好事都让你一个人占了呢。 ——《武林外传》

被折叠的 条评论
为什么被折叠?



