「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目描述
给你一个区间列表,请你删除列表中被其他区间所覆盖的区间。
只有当 c <= a 且 b <= d 时,我们才认为区间 [a,b) 被区间 [c,d) 覆盖。
在完成所有删除操作后,请你返回列表中剩余区间的数目。
示例:
输入:intervals = [[1,4],[3,6],[2,8]] 输出:2 解释:区间 [3,6] 被区间 [2,8] 覆盖,所以它被删除了。
提示:
- 1 <= intervals.length <= 1000
- 0 <= intervals[i][0] < intervals[i][1] <= 10^5
- 对于所有的 i != j:intervals[i] != intervals[j]
分析
理解完题意我们就会发现其实所谓的删除可以将小的区间直接替换为大的区间,我们使用排序的时候直接按照intervals[i][0]来排序,如果他们两者若是相等,则intervals[i][1]大的排在前头,记此以往,就可以删除我们覆盖的数组。
解法1:排序
思路:我们先对所有区间按左端点升序排序,如果左端点相同,按右端点升序排序,这样一来如果有覆盖,一定是前面的覆盖后面的,对每一个区间,判断其后面有多少元素的右端点是小于当前元素的有右端点,并从区间的总数量中减去
var removeCoveredIntervals = function(intervals) {
intervals.sort((a,b) => {
if(a[0] == b[0]){
return b[1] - a[1];
}else{
return a[0]- b[0];
}
})
let right = intervals[0][1],
res = 0;
for(let i = 1; i < intervals.length; i++){
if(right >= intervals[i][1]){
res++;
}
else if(right >= intervals[i][0] && right < intervals[i][1]){
right = intervals[i][1];
}
else{
right = intervals[i][1];
}
}
return intervals.length - res;
};
解法2:双指针
思路:也可以通过双指针,头尾指向移动来实现,每当移动头尾指针比较相同时,就删去当前元素即可,直到两指针相对。
var removeCoveredIntervals = function(intervals) {
let { length } = intervals;
for(let i = 0, j = length - 1; i < length; i++){
while(j >= 0 && j != i){
if(intervals[j][0] <= intervals[i][0] && intervals[j][1] >= intervals[i][1]){
intervals.splice(i, 1);
i -= 1;
length = intervals.length;
break;
}else if(intervals[j][0] >= intervals[i][0] && intervals[j][1] <= intervals[i][1]){
intervals.splice(j, 1);
length = intervals.length;
}
j--;
}
j = length - 1;
}
return intervals.length;
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤