leetcode 57. Insert Interval
Posted =w=
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 57. Insert Interval相关的知识,希望对你有一定的参考价值。
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的主要内容,如果未能解决你的问题,请参考以下文章