LeetCode算法打卡--区间问题

57. 插入区间

给出一个无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

链接:https://leetcode-cn.com/problems/insert-interval/

/*基本思想:先找到要插入的区间的位置,拆入之后,区间合并
 如果插入式头,那就从后面判断合并的区间,找后面的start大于插入区间end的位置(第一个不重叠的),重叠合并,不重叠之间加入结果
 如果是插入中间部分,从插入的位置从前找不重叠的部分加入结果,end<i的start为重叠,先确定合并区间的头,尾先不能确定,将插入的区间的尾编程当前重叠区间最大的,防止后面还可能合并,
 然后找后面第一个不重叠的部分,重叠的合并,不重叠的直接加入结果
*/
class Solution {
public:
    vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
        int i=0,j=0;
        vector<vector<int>> res;
        vector<int> new_inter;
        if(intervals.size()==0)
        {
            res.push_back(newInterval);
            return res;
        }
      
        while( i<intervals.size()&&intervals[i][0]<=newInterval[0] )   //找到要插入的位置为i
        {
           i++;
        }
       
        intervals.insert(intervals.begin()+i,newInterval);  //插入区间
        
        if(i!=0){    //如果插入不是头部插入
        while( j<i&&intervals[i][0]>intervals[j][1] )   //找到第一个不重叠的区域
        {
            res.push_back(intervals[j]);
            j++;
        }
        new_inter.push_back(intervals[j][0]);  //重叠区域合并的start
       
        intervals[i][1] = max(intervals[i][1],intervals[j][1]);   
        cout<<intervals[i][1]<<endl;
        
        j=i+1;
        
        if(j>=intervals.size())
        {
           
            new_inter.push_back(intervals[i][1]);
            res.push_back(new_inter);
            return res;
        }
        while( j<intervals.size()&&intervals[i][1]>=intervals[j][0]  )  //后面找第一个不重叠的
        {
            j++;
        }
        new_inter.push_back(max(intervals[j-1][1],intervals[i][1]));  //重叠区域合并找到合并的end
        res.push_back(new_inter);
        while(j<intervals.size())     //不重叠的直接加入结果
        {
            res.push_back(intervals[j]);
            j++;
        }
        }
        else
        {
            j=i+1;
            while(j<intervals.size() && intervals[i][1]>=intervals[j][0] )   //找后面的start大于插入区间end的位置(第一个不重叠的)
                j++;  
            new_inter.push_back(intervals[i][0]);                            //插入的区间判断合并
           
            new_inter.push_back(max(intervals[j-1][1],intervals[i][1]));    //重叠部分的end取最大的
           
            
            res.push_back(new_inter);
             while(j<intervals.size())   //之后全部不重叠直接加入就好
        {
            res.push_back(intervals[j]);
            j++;
        }
            
  
        }
        return res;
        
    }
};

435. 无重叠区间

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。


链接:https://leetcode-cn.com/problems/non-overlapping-intervals

class Solution {
public:
 /*贪心:按数组首数字从小到大排序,然后判断区间:判断尾元素有下面几种情况
    1.i的尾<=j的头  无重叠,可以让i变为j,然后j继续向后移动比较
    2.i的尾>j的头,有重叠, 则删除i和j尾大的同时数量count加1
          如果i的尾大:则i=j 用j代替i j++ 向后比较
          如果j的尾大:则i不变,j++,向后比较

  
  
  */ 
    
    static bool cmp(const vector<int> a,const vector<int> b)
    {
        
            return a[0]<b[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        
        sort(intervals.begin(),intervals.end(),cmp);
        int i=0,j=1;
        int count=0;
        
           for(j=1;j<intervals.size();j++)
            {
                if(intervals[i][1] <= intervals[j][0])
                {
                    i=j;
                    
                }
                else
                {
                   if(intervals[i][1] > intervals[j][1])
        
                        i=j;
                        
                    count++;
                }    
                
        }
        return count;
    }
};

56. 合并区间

给出一个区间的集合,请合并所有重叠的区间。

链接:https://leetcode-cn.com/problems/merge-intervals/

/*基本思想:两种方法 都先把数组按照开始值从小到大排序
          方法一:从开始遍历,找第一个end<start的位置,就是不重叠的位置,前面重叠的部分合并,确定合并的end,确定新的区间,然后继续找下一个与新区间的end不重叠的位置
          方法二:直接遍历比较,首先插入一个区间,继续插入的时候判断是否重叠,重叠,更新刚插入的区间的end,否则插入新的区间,利用vector的back函数可以取到最后拆入的区间,直接比较更新就好
*/
class Solution {
public:
    static bool cmp(vector<int> a, vector<int> b)
    {
        return a[0]<b[0];
    }
   /* vector<vector<int>> merge(vector<vector<int>>& intervals) {
        int i=0,j=0;
        vector<vector<int>> res; 
        if(intervals.size()==0)
            return res;
        
        sort(intervals.begin(),intervals.end(),cmp); 
       
        while(i<intervals.size())
        { 
            int end;
            vector<int>cur;
           
            cur.push_back(intervals[i][0]);
            
             end = intervals[i][1];
           
            j=i+1;
          
            while(j<intervals.size() && end>=intervals[j][0]  )
            {
                 end = max(end,intervals[j][1]);
                 j++;
            }
           
            cur.push_back(end);
            i=j;
            res.push_back(cur);
        }
        return res;
    }*/
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> res;
        if(intervals.size()<1){
            return res;
        }
        sort(intervals.begin(),intervals.end(),cmp);
        res.push_back(intervals[0]);
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]<=res.back()[1]){
                res.back()[1]=max(intervals[i][1],res.back()[1]);
            }
            else{
                res.push_back(intervals[i]);
            }
        }
        return res;
    }
};

986. 区间列表的交集

给定两个由一些闭区间组成的列表,每个区间列表都是成对不相交的,并且已经排序。

返回这两个区间列表的交集。

(形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b。两个闭区间的交集是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3]。)


链接:https://leetcode-cn.com/problems/interval-list-intersections

/*基本思路:思路1:以B为基准,A和B依次比较,当A的最大值大于B的最小值的时候,才有交集,求出交集排除异常情况即可
           思路2: A和B同时移动比较,不满足交集条件的一方移动(每个集合都是有序的),满足条件则判断交集
*/

class Solution {
public:
   
    /* vector<vector<int>> intervalIntersection(vector<vector<int>>& A, vector<vector<int>>& B) {
        int i,j=0;
        vector<vector<int>> result;
        if(A.size()==0)
            return A;
        if(B.size()==0)
            return B;
        for(i=0;i<A.size();i++)
        {
            vector<int> r;
            
            for(j=0;j<B.size();j++){
             
             if(A[i][1]<B[j][0])  
                continue;
        
             int left =max(A[i][0],B[j][0]);
             int right =min(A[i][1],B[j][1]);
             if(left<=right)
             {
                 r.push_back(left);
                 r.push_back(right);
                 result.push_back(r);
                 r.clear();
             }
             
           
            
            }
            
        }
            
            
            return result;
                  
        
    }*/
    
    vector<vector<int>> intervalIntersection(vector<vector<int>>& A, vector<vector<int>>& B) {
        int cnt = 0;
        vector<vector<int>> vec;
        vector<int> tmp(2);
        for(int i=0;i<A.size()&&cnt<B.size();)
        {
            if(A[i][0]>B[cnt][1])
            {
                cnt++;
            }
            else if(A[i][1]<B[cnt][0])
            {
                i++;
            }
            else if(A[i][1]<B[cnt][1])
            {
                tmp[0] = max(A[i][0],B[cnt][0]);
                tmp[1] = A[i][1];
                vec.push_back(tmp);
                i++;
            }
            else
            {
                tmp[0] = max(A[i][0],B[cnt][0]);
                tmp[1] = B[cnt][1];
                vec.push_back(tmp);
                cnt++;
            }
        }
        return vec;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值