当前位置:   article > 正文

【c++】常见区间算法问题整理_c++区间问题

c++区间问题

一、删除覆盖区间

题目:

给一个区间数组,删除最小个数的、被覆盖的区间,返回最终删除覆盖区间后剩余的区间个数。对于区间[a,b)和[c,d)当且仅当c>=a且d<=b的时候,a-b完全覆盖c-d

区间算法解决的重点

1、升序排列,定出区间之间左端点的关系,只需使用右端点即可得到区间关系,简化操作

2、区间关系有三种:

  • 完全覆盖,即某一区间左右端点都被包含在内
  • 部分覆盖,有一部分伸出来,此时可以扩展现已覆盖的总区间的左右边界
  • 不相交

解题思路:

!注意:在这个题目中,由于升序排列区间之后,能产生覆盖只可能在相邻的区间中产生覆盖,因此,只需要用left和right记录此时最邻近的、已覆盖的最大区间,由此判断下一个区间是否会产生完全覆盖

小坑记录:

bool比较函数传入sort方法的时候,请用static定义

代码如下:

  1. class Solution {
  2. public:
  3. static bool compare(const vector<int>&a,const vector<int>&b){
  4. if(a[0]<b[0]) return true;
  5. else if(a[0]==b[0] && a[1]<b[1]) return true;
  6. else return false;
  7. }
  8. int removeCoveredIntervals(vector<vector<int>>& intervals) {
  9. //升序排列
  10. sort(intervals.begin(),intervals.end(),compare);
  11. //只有当完全被覆盖的时候删除
  12. //只需要记录left和right即当前已存在的最大区间的左右边界
  13. //由于本身就是升序排列的,那么,当遇到断开的不交集新区间,重新赋值left、right即可,因为区间升序排列,只可能在邻近区间操作
  14. int left=intervals[0][0],right=intervals[0][1];
  15. int count=intervals.size();
  16. for(int i=1;i<intervals.size();i++){
  17. cout<<left<<" "<<right<<endl;
  18. //区间关系分为三种情况:
  19. //1、完全覆盖
  20. //2、有交集,合并为大区间
  21. //3、无交集,更新为新区间
  22. if(intervals[i][0]>=left && intervals[i][1]<=right){
  23. count--;
  24. }
  25. else if(right>=intervals[i][0] && right<=intervals[i][1]){
  26. //注意,这里之所以不考虑left的关系,是因为left必然小于等于新遍历到的区间->这就是升序排列控制的性质
  27. right=intervals[i][1];
  28. }
  29. else{
  30. left=intervals[i][0];
  31. right=intervals[i][1];
  32. }
  33. }
  34. return count;
  35. }
  36. };

二、合并区间

题目:将区间合并为不相交区间列表

力扣:合并区间

按照上面所说的区间关系,记录left和right,不断更新

在断开区间的时候或者在遍历末尾,将新纪录的区间放入

  1. class Solution {
  2. public:
  3. static bool compare(const vector<int> & a,const vector<int> &b){
  4. if(a[0]<b[0]) return true;
  5. else if(a[0]==b[0] && a[1]<b[1]) return true;
  6. else return false;
  7. }
  8. vector<vector<int>> merge(vector<vector<int>>& intervals) {
  9. vector<vector<int>> mergeInterval;
  10. //排序
  11. sort(intervals.begin(),intervals.end(),compare);
  12. int left=intervals[0][0],right=intervals[0][1];
  13. for(int i=1;i<intervals.size();i++){
  14. //部分覆盖
  15. if(right>=intervals[i][0] && right<=intervals[i][1]) right=intervals[i][1];
  16. else if(right<intervals[i][0]){//没有交集
  17. //刷新,存入区间
  18. vector<int> qujian;
  19. qujian.push_back(left);
  20. qujian.push_back(right);
  21. mergeInterval.push_back(qujian);
  22. //更新left 和 right
  23. left=intervals[i][0];
  24. right=intervals[i][1];
  25. }
  26. }
  27. //最后,记录下来的合并区间,最新的,还没来得及放入到数组中,最后继续放入
  28. vector<int> qujian;
  29. qujian.push_back(left);
  30. qujian.push_back(right);
  31. mergeInterval.push_back(qujian);
  32. return mergeInterval;
  33. }
  34. };

三、区间之间的交集

 题目:两个不相交的、已升序排列的区间列表,求出两个区间列表之间存在的相交区间集合(集合左闭右闭)

力扣:区间之间的交集算法

解题思路:

1、双指针法,根据升序、不相交的特性,每次对比,移动具有更小右值的区间列表的指针【这样的移动可能会带来又一次相交

2、计算相交区间

上面讨论了区间有三种宏观上的关系,除了不相交以外,都可以归为相交情况。但是相交区间要求具体的相交范围,可以总结为以下4种可能性

相交区间的关系

对于区间[a1,b1]和[a2,b2]

  • 若a1>=a2并且b1<=b2,则相交区间为[a1,b1]
  • 若a2>=a1并且b2<=b1,则相交区间为[a2,b2]
  • 若a2>=a1并且b1<=b2,则相交区间为[a2,b1]
  • 若a1>=a2并且b2<=b1,则相交区间为[a1,b2]

总结下来如下图所示:

image.png

 由上述规律总结,对于两个区间的交集部分,设为[c1,c2]

c1=max(a1,a2).    c2=min(b1,b2)

代码如下:

  1. class Solution {
  2. public:
  3. vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
  4. vector<vector<int>> res;
  5. int len1=firstList.size(),len2=secondList.size();
  6. //特殊情况,两个区间列表一样没有交集
  7. if(!len1 || !len2 || firstList[len1-1][1]<secondList[0][0] || secondList[len2-1][1]<firstList[0][0]) return res;
  8. //双指针法
  9. int j=0,i=0;
  10. while(i<len1 && j<len2){
  11. //如果不是完全不相交
  12. if(!(firstList[i][0]>secondList[j][1] || firstList[i][1]<secondList[j][0])) {
  13. vector<int> seq;
  14. //相交的区间有四种情况,总结来就是取边界
  15. int left=max(firstList[i][0],secondList[j][0]);
  16. int right=min(firstList[i][1],secondList[j][1]);
  17. seq.push_back(left);
  18. seq.push_back(right);
  19. res.push_back(seq);
  20. }
  21. //注意:每个区间列表中都是升序、不相交的;所以下一个区间的左值一定大于上一个区间的有值
  22. //所以还可能继续被交的【即右值范围更大的留着】,另一个的列表指针移动
  23. if(firstList[i][1]<secondList[j][1]){
  24. i++;
  25. }
  26. else j++;
  27. }
  28. return res;
  29. }
  30. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/654216
推荐阅读
相关标签
  

闽ICP备14008679号