区间问题:
给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数,起止相连不算重叠。 输入是一个数组,数组由多个长度固定为 2 的数组组成,表示区间的开始和结尾。 输出一个整数,表示需要移除的区间数量。
Input: [[1,2], [2,4], [1,3]]
Output: 1
可以移除区间 [1,3],使得剩余的区间 [[1,2], [2,4]] 互不重叠 思考: 这道题目第一次没看懂,区间重叠指的是啥。看了解析说明后,原来是12 13,两个数组元素1,2重叠,所以就是区间重叠了。
自己解题思路:
每个数组有起始和结束,当前数组结束元素<=下一个起始元素。
如果[1,2] end:2,[2,4] star:2 end:4, [1,3]star:1 end:3 比如: [end:2 <= star:2] [end:4 <= star:1] 不成立移除+1
#include <iostream>
#include <vector>
const int FindMoveInterval(const std::vector<int*>& arrays)
{
const size_t arrayslen = arrays.size();
// 如果就一个元素不需要移除
if (arrayslen <= 1)
return 0;
// 遍历二维数组
size_t idx = 0, removelen = 0;
for (idx = 0; idx < arrayslen; ++idx)
{
// 最后一个元素break,否则越界
if ((arrayslen - idx) == 1)
break;
if (arrays[idx][1] > arrays[idx + 1][0])
removelen++;
}
return removelen;
}
int main()
{
std::vector<int*> intervalvec;
int data[] = { 1,2 };
int data1[] = { 2,4 };
int data2[] = { 1,3 };
intervalvec.push_back(data);
intervalvec.push_back(data1);
intervalvec.push_back(data2);
const int intervals = FindMoveInterval(intervalvec);
printf("移除区间: %d\n", intervals);
system("pause");
}
再写上述代码时候,脑海中完全没有想过贪心算法,我甚至不知道写出来的代码和贪心算法有没有关系,从代码运行后的结果和题意理解来看应该一样。
贪心算法要比自己写的好在哪里?或者到底麻烦不麻烦?来看下pdf 2.3给出的解题思路: 在选择要保留区间时,区间的结尾十分重要:选择的区间结尾越小,余留给其它区间的空间就越大,就越能保留更多的区间。因此,我们采取的贪心策略为,优先保留结尾小且不相交的区间。
贪心思路:
- 优先保留结尾小且不相交
- 按照结尾的大小进行增序排序,每次选择结尾最小且和前一个选择的区间不重叠的区间。
int eraseOverlapIntervals(std::vector<std::vector<int>>& intervals) {
if (intervals.empty()) {
return 0;
}
int n = intervals.size();
// 这里写法太骚,一时间没看懂
std::sort(intervals.begin(), intervals.end(), [](std::vector<int>& a, std::vector<int>& b)
{
return a[1] < b[1];
});
int removed = 0, prev = intervals[0][1];
for (int i = 1; i < n; ++i) {
if (intervals[i][0] < prev) {
++removed;
}
else {
prev = intervals[i][1];
}
}
return removed;
}
看完以后感觉代码挺骚写的,怀疑自己写的不对,所以分别调用输入:
Input: [[1,2], [2,4], [1,3], [3,4], [1,3], [5,6], [9,9], [2,3]]
int main()
{
std::vector<std::vector<int>> vectoraa;
vectoraa.push_back({ 1,2 });
vectoraa.push_back({ 2,4 });
vectoraa.push_back({ 1,3 });
vectoraa.push_back({ 3,4 });
vectoraa.push_back({ 1,3 });
vectoraa.push_back({ 5,6 });
vectoraa.push_back({ 9,9 });
vectoraa.push_back({ 2,3 });
const int intervals1 = eraseOverlapIntervals(vectoraa);
printf("eraseOverlapIntervals Output: %d\n", intervals1);
std::vector<int*> intervalvec;
int data[] = { 1,2 };
int data1[] = { 2,4 };
int data2[] = { 1,3 };
int data3[] = { 3,4 };
int data4[] = { 1,3 };
int data5[] = { 5,6 };
int data6[] = { 9,9 };
int data7[] = { 2,3 };
intervalvec.push_back(data);
intervalvec.push_back(data1);
intervalvec.push_back(data2);
intervalvec.push_back(data3);
intervalvec.push_back(data4);
intervalvec.push_back(data5);
intervalvec.push_back(data6);
intervalvec.push_back(data7);
const int intervals = FindMoveInterval(intervalvec);
printf("FindMoveInterval Output: %d\n", intervals);
system("pause");
}
eraseOverlapIntervals输出: 3
FindMoveInterval输出: 3
LeetCode Github See 2.3: https://github.com/changgyhub/leetcode_101/
LeetCode See:https://leetcode.com/problems/non-overlapping-intervals/