前言
今天,我们来学习贪心算法的另外一道题目:无重叠区域,这道题思路上和使用最少的箭射爆气球十分相似。闲话不多说,我们直接来看题目。
题目描述
给定一个区间的集合 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 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
题意解析
- 首先我们要明确什么是无定义区间———— 一个区间的集合中,任意两个区间均不重叠
- 什么时候算重叠呢?———— 前面一个区间的右边界大于后面一个区间的左边界
思路解析
- 我们首先需要将区间的集合进行排序 ————因为我们需要使重合的区间挨在一起,这样方便我们去判断它们是否重叠
- 那我们根据什么进行排序呢?————既可以根据子区间的左边界也可以根据子区间的右边界,根据左边界还是有边界进行排序无所谓,反正我们排序的目的,只是为了让重合区间挨在一起而已。
- 如何判断重叠呢?————前面区间的右边界大于后面区间的左边界
- 重叠之后,我们应该怎样做呢?
- 首先,计数器++,因为我们要得到无重叠区间,只需要把重叠的区间删掉即可,当然,我们不需要真的去集合中删除重叠区间,题目只是要得到需要删除的个数,所以我们只需要计数即可。
- 其次,本题中我们不需要更新右边界,因为,我们只需要确认两个区间是否重叠,不考虑俩个以上的区间是否重叠的问题。这是与“使用最少的箭射爆气球”题目的不同之处。
5.不重叠了,我们应该做什么呢?
- 我们需要更新右边界,既然前面的不重叠了,我们就需要将后面的区间与当前的区间的右边界进行对比。
我们以:[[1,2],[2,3],[3,4],[1,3]]为例,进行画图说明:
根据左边界进行排序
根据排序之后的集合,我们可以看到:
- [1,2]和[1,3]重叠了,[1,3]是需要去除的区间,我们将它记录下来
- [1,2]和[2,3] 不重叠
- [2,3]和[3,4]不重叠
所以,我们最后输出值为:1,即我们需要删除一个区间,使集合为不重叠区间
根据右边界进行排序
根据排序之后我们可以看到:
- [1,2]和[2,3] 不重叠
- [2,3]和[1,3]重叠了,[1,3]是需要去除的区间,我们将它记录下来
- [2,3]和[3,4]不重叠
所以,我们最后输出值为:1,即我们需要删除一个区间,使集合为不重叠区间
伪代码(只描述代码思路)
根据左边界进行排序:
[ [1,2], [2,3], [3,4], [1,3] ]
Function mian(arr){
Let count=0;
//排序-根据左边界进行排序
arr.sort((a,b)=>a[0]-b[0])
let right=arr[0][1]
for(let i=1;i<arr.length;i++){
//重合了
if(arr[i][0]<right){
count++
}else{
right=arr[i][1]
}
}
Return count
}
根据右边界进行排序:
[ [1,2], [2,3], [3,4], [1,3] ]
Function mian(arr){
Let count=0;
//排序-根据左边界进行排序
arr.sort((a,b)=>a[1]-b[1])
let right=arr[0][1]
for(let i=1;i<arr.length;i++){
//重合了
if(arr[i][0]<right){
count++
}else{
right=arr[i][1]
}
}
Return count
}
总结
今天的贪心算法学习就到这里了,如有错误之处,欢迎大家留言指出。谢谢大家了。