一、题目
给定一个区间的集合 intervals
,其中 intervals[i] = [starti, endi]
。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
示例 1:
输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:
输入: intervals = [ [1,2], [1,2], [1,2] ] 输出: 2 解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:
输入: intervals = [ [1,2], [2,3] ] 输出: 0 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
二、解题思路
要解决这个问题,我们可以使用贪心算法。贪心算法的核心思想是在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的。
对于这个问题,我们可以按照以下步骤进行:
-
按照区间的结束时间进行排序:这样可以确保我们优先选择结束时间早的区间,从而给后面的区间留下更多的空间。
-
遍历排序后的区间:从第二个区间开始,检查当前区间的开始时间是否与前一个区间的结束时间重叠。如果重叠,则需要移除当前区间(因为我们要尽量保留结束时间早的区间);如果不重叠,则保留当前区间。
-
记录移除的区间数量:在遍历过程中,记录需要移除的区间数量。
具体实现步骤如下:
-
将区间按照结束时间进行排序。
-
初始化一个变量
remove_count
用于记录移除的区间数量,初始化为 0。 -
初始化一个变量
prev_end
用于记录前一个区间的结束时间,初始化为第一个区间的结束时间。 -
从第二个区间开始遍历,如果当前区间的开始时间小于
prev_end
,则说明当前区间与前一个区间重叠,需要移除,remove_count
加 1。 -
如果当前区间的开始时间大于或等于
prev_end
,则说明当前区间与前一个区间不重叠,更新prev_end
为当前区间的结束时间。 -
遍历结束后,返回
remove_count
。
三、代码实现
#include <iostream>
#include <vector>
#include <algorithm>
// 比较函数,用于排序
bool compareIntervals(const std::vector<int>& a, const std::vector<int>& b) {
return a[1] < b[1];
}
int eraseOverlapIntervals(std::vector<std::vector<int>>& intervals) {
if (intervals.empty()) {
return 0;
}
// 按照结束时间进行排序
std::sort(intervals.begin(), intervals.end(), compareIntervals);
int remove_count = 0;
int prev_end = intervals[0][1];
for (size_t i = 1; i < intervals.size(); ++i) {
if (intervals[i][0] < prev_end) {
// 当前区间与前一个区间重叠,需要移除
++remove_count;
} else {
// 当前区间与前一个区间不重叠,更新 prev_end
prev_end = intervals[i][1];
}
}
return remove_count;
}
int main() {
std::vector<std::vector<int>> intervals1 = {{1, 2}, {2, 3}, {3, 4}, {1, 3}};
std::cout << "Example 1: " << eraseOverlapIntervals(intervals1) << std::endl; // 输出: 1
return 0;
}