写在前边
- 可以算是第一次写博客,用以记录剩下的两年半大学时光和祭奠荒废了的大一,并且以此为勉,更加努力!
正文
首先看题目描述:
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
示例 1:
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
-解释: 移除 [1,3] 后,剩下的区间没有重叠。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/non-overlapping-intervals
-
因为是刚开始刷题,所以对于这种题目不是很熟悉,自身也没有参加算法比赛的经历。所以看到这道题十分的懵。尝试无果之后去看了题解。
-
题解中大多数人提到了贪心算法,而贪心算法对我而言仅仅是了解,只是在数据结构课上提起prim和kruskal算法的时候提到过,具体怎么实现我却不是很清楚。于是我去查找了贪心算法的介绍,例题等,因为时间关系我理解的还不是很透彻,下面是我对贪心算法的一些简单理解。
所谓贪心,是一个不怎么好的词,而这个算法也可以这么理解。不需要有大局观和整体意识,只需要在每一步做到最好,得到最优解,那么在最后也会得到最优解。
-
就是带着这样的理解,我看了几道例题。令我比较惊讶的是,我看到的两道例题无一例外是用最小堆完成的,刚好是我的数据结构程序设计题。。。。令我有些迷惑。因此最后我还是去看了上边这道题的题解。
-
代码十分简单甚至优美,感兴趣的可以去亲自看一看,就在这道题的评论区。一方面我对算法更加的敬畏,另一方面也十分愧疚自己实力不够。
-
对于这道题,含有K个区间,要求去掉的区间最少,换言之就是留下的最多。而留下的区间又是全部不重叠的。对于第一个区间来说,只有该区间右段足够小,才能给后边空出足够的位置放下更多的数组。当然这是在不重叠的情况下。因此考虑先将所有区间按照右端点的大小排序,其中最小的作为第一个区间,不妨令该区间的右端为i,考虑到不重叠,下一个区间的左端一定大于等于i,检索到这样一个区间之后,将其作为下一个区间(记得,此时我们将所有区间按照右端排过序了,因此检索到第一个满足条件的区间的右端,一定是所有满足条件的区间中最小的!),然后依次进行直到将所有的区间找完。
-
代码的具体实现:
#include"iostream"
#include"vector"
#include"algorithm"
using namespace std;
bool cmp(vector<int> a, vector<int> b) //自我实现的排序函数
{
if (a[1] < b[1])
{
return true;
}
else
{
return false;
}
}
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), cmp); //对所有的区间按照右端排序。
int count = 1; //计数,记录剩下的区间有几个
int end = intervals[0][1];//将第一个的右端点作为标志
for (int i = 1; i < intervals.size(); i++)
{
if (intervals[i][0] >= end)
{
end = intervals[i][1];
count++;
}
}
return intervals.size() - count;
}
};
int main()
{
vector<vector<int>> v(4);
v[0].push_back(1);
v[0].push_back(2);
v[1].push_back(2);
v[1].push_back(3);
v[2].push_back(3);
v[2].push_back(4);
v[3].push_back(1);
v[3].push_back(4);
Solution s;
cout << s.eraseOverlapIntervals(v) << endl;
system("pause");
return 0;
}`
- 但是我这样还有一点问题。。。叫的时候WA了三发,去看了一下答案,原来是没有判断vector为空的情况。。。看来还是需要注意细节。
- 也算是第一次亲手写博客,刚开始学算法,现在做题还是靠看题解得到思路,希望自己早日自己解决难题!