57. Insert Interval

这道题有三种解法,其中两种跟上一题,merge interval有些相似。


1.直接把新的区间接在区间列表的后面,然后sort,merge interval。这么简单就不贴代码了。

2. 从前往后遍历已知的区间集合,当找到第一个起始位置大于要插入区间起始位置的元素的时候,插入新的区间。然后按照merge interval的方法改变上一个插入的区间,或者插入新的区间。这个做法徐杰实现有挺多地方要注意的。比如第一个插入的是新区间怎么办,新区间和很多已有的区间都有重合怎么办,要插入的跟在最后,和所有的都没有重合怎么办。

vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        sort(intervals.begin(), intervals.end(),[](const Interval& left, 
                const Interval& right){return left.start<right.start;});
        vector<Interval> res;
        bool used=false;
        for(int i=0;i<=intervals.size();++i){
            if(used&&i==intervals.size())
                break;
            Interval nextit;
            if(used==false&&(i==intervals.size()||intervals[i].start>newInterval.start)){
                nextit=newInterval;
                used = true;
                i--;
            }
            else{
                nextit=intervals[i];
            }
            if(res.empty()||res.back().end<nextit.start)
                res.push_back(nextit);
            else
                res.back().end=max(res.back().end,nextit.end);
        }
        if(res.empty())
            res.push_back(newInterval);
        return res;
    }
第2和第一种解法在lc运行的时候,时间上没有特别本质的差别,大概差了30几ms。但是如果先前给的区间序列是排好序的话,那么第二种解法的有点就体现出来了。第一种解法需要排序,所以复杂度是O(nlogn), 第二种是O(n)。

在网上还流传着第三种解法。和第二种解法的区别之处是,只要插入了res数组的元素就不发生变化了。在便利给定区间集合的过程中,如果当前区间和新区建有交集,那么改变新的区间。直到遇见和新区建没有交集的区间,再把经过很多次更改的新区间放到数组里。之后所有的区间直接copy。

我直接复制的这位同学的代码 http://bangbingsyb.blogspot.com/2014/11/leetcode-insert-interval.html 有时间了我自己照猫画虎,看看能不能写出来

vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
        vector<Interval> ret;
        bool isInsert = false;
        for(int i=0; i<intervals.size(); i++) {
            // already insert newInterval
            if(isInsert) {  
                ret.push_back(intervals[i]);
                continue;
            }
            
            // insert newInterval before current interval
            if(newInterval.end < intervals[i].start) {  
                ret.push_back(newInterval);
                ret.push_back(intervals[i]);
                isInsert = true;
                continue;
            }
            
            // combine newInterval with current interval
            if(newInterval.start<=intervals[i].end && intervals[i].start<=newInterval.end) {
                newInterval.start = min(newInterval.start, intervals[i].start);
                newInterval.end = max(newInterval.end, intervals[i].end);
                continue;
            }
            
            // newInterval after current interval
            ret.push_back(intervals[i]);
        }
        
        if(!isInsert) ret.push_back(newInterval);
        return ret;
    }

当然了,这道题也有空间复杂度是常数的解法。思路基本和上一中解法相同,插入新区建,一直删除之后和他相交的,在这个过程中更新前后界。但是问题还是一样,如果遇见就集合是[[2,3],[4,5],[5,6],....,[1001,1002]]这样的区间,而插入的新区间是[1,1002],就要删除好多元素,复杂度就很高了。

vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval>::iterator it = intervals.begin();  
            while(it!= intervals.end())  
            {  
                 if(newInterval.end<it->start)  
                 {  
                      intervals.insert(it, newInterval);  
                      return intervals;  
                 }  
                 else if(newInterval.start > it->end)  
                 {  
                      it++;  
                      continue;  
                 }  
                 else  
                 {  
                      newInterval.start = min(newInterval.start, it->start);  
                      newInterval.end = max(newInterval.end, it->end);  
                      it =intervals.erase(it);                      
                 }                 
            }  
            intervals.insert(intervals.end(), newInterval);            
            return intervals;            
    }

as expected, lc 超时额


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值