zoukankan      html  css  js  c++  java
  • 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;
        }
    };
  • 相关阅读:
    sql server 数据库优化显示执行计划
    你真的了解SQL的索引吗?
    温习Remoting基础
    sql 百万级数据库优化方案
    MYSQL——查看显示数据库
    输入框【普通输入框,邮箱输入框,验证码输入框,手机号码输入框】的测试用例规范
    一个完整的测试计划包含哪些内容?
    MYSQL——多表查询
    软件测试功能性需求(Functional requirement)+非功能性需求(Nonfunctional requirement)
    【自动化测试01】如何配置Android SDK环境变量
  • 原文地址:https://www.cnblogs.com/bbbbbq/p/7624632.html
Copyright © 2011-2022 走看看