leetcode 57. Insert Interval

Posted =w=

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 57. Insert Interval相关的知识,希望对你有一定的参考价值。

link 

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times.

Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].

Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].

This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].

 

题意:

给几段不相交的区间,顺序按左端点排序。

插入一个新的区间。这段区间的插入可能会使其中一些区间变得连续。 

输出新的不相交的区间。

表达无能,example 非常明白。

 

思路:

确定新区间的位置。

首先二分寻找出最大的i,满足intervals[i].end < newInterval.start。于此i+1(若存在)有三种可能,如下图

一种红色的,newInterval和i+1不相交, 则新区间左端点为newInterval.start

一种蓝色的,newInterval和i+1相交,新的区间的左端点为newInterval.start

一种绿色的,newInterval和i+1相交,新的区间的左端点为intervals[i+1].start

因此可以看出,新的区间的左端点为min(newInterval.start, intervals[i+1].start)

同理二分找出最小的i满足intervals[i].start > newInterval.end.i-1为要处理的区间。 更新出新区间的右端点。

要处理的特例是没有i+1/i-1的情况,其实也就是newInterval和后面/前面不相交的时候,因此更新为newInterval的信息即可。

 

接下来所有和newInterval有重叠的区间都不用push进最后的结果,因为他们会被作为一个新的区间的整体被放入。我们只用push进不相交的部分。也即

intervals[i].end < left_side ,
intervals[i].start > right_side
这两个部分。

当第一次要加入

intervals[i].start > right_side

之前,我们要把新区间放进去。

 

注意:用in来保证新区间被push了。存在新区间在所有老区间的后方的情况,此时

intervals[i].start > right_side 不会被满足。要在最后特判放入

代码:

class Solution {

public:
    int find_left(vector<Interval>& intervals, Interval newInterval){
        int l = 0, r = intervals.size() - 1;
        int ans = -1;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(intervals[mid].end < newInterval.start){
                ans = mid;
                l = mid + 1;
            }else{
                r = mid - 1;
            }
        }
        return ans;
    }
    int find_right(vector<Interval>& intervals, Interval newInterval){
        int l = 0, r = intervals.size() - 1;
        int ans = intervals.size();
        while(l <= r){
            int mid = (l + r) >> 1;
            if(intervals[mid].start > newInterval.end){
                ans = mid;
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        return ans;
    }

    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> ans;
        if(intervals.size() == 0) {
            ans.push_back(newInterval);
            return ans;
        }
        // 寻找最大的i满足intervals[i].end < newInterval.start
        int front = find_left(intervals, newInterval);
        int left_side;
        if(front == intervals.size() - 1 ){ //|| front == -1){
            left_side = newInterval.start;
        }else{
            left_side = min(intervals[front + 1].start, newInterval.start);
        }
        // 寻找最小的i满足intervals[i].start > newInterval.end
        int tail = find_right(intervals, newInterval);
        int right_side;
        if(tail == 0 ){//|| tail == intervals.size()){
            right_side =newInterval.end;
        }else{
            right_side = max(newInterval.end, intervals[tail-1].end);
        }
        // 以上凭此判定新区间的左右端点。
        
        // 遍历所有区间。若其在新区间左边,则push, 否则在第一次在新区间的右边的时候push新区间
        bool in = false;
        for(int i = 0; i < intervals.size(); i++){
            if(intervals[i].end < left_side) ans.push_back(intervals[i]);
            else if(intervals[i].start > right_side){
                if(!in){
                    in = true;
                    ans.push_back(Interval(left_side, right_side));
                }
                ans.push_back(intervals[i]);

            }
        }
        if(!in) ans.push_back(Interval(left_side, right_side));  // 注意,若新区间没有被push过,则要push一次
        return ans;
    }
};

 

以上是关于leetcode 57. Insert Interval的主要内容,如果未能解决你的问题,请参考以下文章

一天一道LeetCode#57. Insert Interval

Leetcode57 Insert Interval

LeetCode57 Insert Interval

Leetcode 57: Insert Interval

leetcode 57. Insert Interval

[LeetCode] 57. Insert Interval Java