LeetCode 57. Insert Interval 题解
2017-10-23 09:07
429 查看
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].
题目分析
这道题大意先给定一个有序区间数组, 再向这个数组里面插入一个区间使其仍然有序, 并对插入后的数组进行区间合并操作,然后返回。嗯。这题我还真不知道为什么是Hard,23333……真的水呀。本来想先试一种暴力解法为一种感觉更优一点的解法做铺垫的,结果发现直接交了成绩还不错,就懒得写更好一点的了2333… -.- 不过思路等下还是会大致讲一下的。
其实这道题…..怎么说呢。可以先确定一个复杂度下界吧。O(m)的下界复杂度, 其中m是返回的合并后的数组长度。毕竟无论怎样你都得构建一个这样的数组 对吧。。。
为啥说这个呢。。。主要是这题水没啥思路好写的。就扯点其他的吧。这个下界知道了还是有一定指导意义的, 会让你之后放弃做一些意义不是很大的优化。。。
嗯不水了。进入正题。这题一个直接的想法就是扫描一遍区间数组, 能插就插入, 该合并就合并啊。。。
话是这样说,如何做呢?
下面就说几点重要的地方吧。 其实画个区间图就能很轻松看出来。
1.
newInterval.start > intervals[i].end时, 表示还没有到插入的区间。此时直接加入
ans就可以了。
2. 处理完上面那个之后的首个
intervals[i]是需要分情况讨论的。先说简单的情况:
newInterval.end < intervals[i].start的时候。证明这个插入的区间不需要合并。(画图显然的)
3. 复杂一点的情况在这里: 如果不满足上面那个条件呢? 那就说明至少有一个区间要和新插入的区间进行合并。而且这些需要合并的区间是连续的(注意这一点, 优化的时候会再用到)
那么朴素的想法就是, 先取
intervals[i]和
newInterval合并,再考察是否满足上面 2 中那个条件, 如果不满足, 继续合并下一个。知道满足为止(满足的话即下一个Interval不会和合并的Interval产生交集)
4. 之后将剩下的直接添加到
ans区间数组里。(合并完成后, 右边的那些不需合并的区间不变)
复杂度分析:
这个算法复杂度主要在于扫描一遍初始数组, 故复杂度易得为O(n),其中 n 为初始数组长度。
划重点: 最坏情况下 m,n同阶, m=n+1, 所以结合刚才推导出的时间复杂度下限, 这算法还算不错:)
(不过这种题为什么是Hard…)
稍微优一点点的解
看到这题其实立马想到的就是二分, 毕竟有序…二分之后为什么可以优化呢? 那就得看前面那个算法复杂在了哪儿了。步骤1, 4是必不可少的。那就只能在
3上面做文章了。 注意到合并的区间连续, 也就是只要确定头尾即可。而二分就是做这样一件事情:确定新插入区间影响原数组的头部和尾部。这样就可以不用执行多次, 而可以一次就合并完了。
这个算法的复杂度是多少呢? 我直接给出下面的公式:
O(max(m,logn))
比较菜, 不确定准确的是不是这样, 但是大致是这样应该没有问题。这个复杂度说明了什么呢? 两个事情:
1. 较好的情况下, 能到达复杂度下界。
2. 较坏的情况, 复杂度和上面第一种方法一样。
还有这样做编程实现有点麻烦。。。所以看到法一的performance还不错就懒了 ~。~
下面是方法一的具体代码实现:
class Solution { public: Interval merge(Interval &a, Interval &b) { return Interval(min(a.start, b.start), max(a.end, b.end)); } vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) { vector<Interval> ans; int i = 0; while (i < intervals.size() && intervals[i].end < newInterval.start) { ans.push_back(intervals[i]); i++; } if (i < intervals.size() && newInterval.end < intervals[i].start) ans.push_back(newInterval); else { auto t = newInterval; while(i < intervals.size() && intervals[i].start <= t.end) { t = merge(t, intervals[i]); i++; } ans.push_back(t); } while (i < intervals.size()) { ans.push_back(intervals[i]); ++i; } return ans; } };
其他细节
emmmm…这题唯一要注意的就是多过程处理时,每个过程交界处的处理要做到不重不漏, 特别小心。 这题我是分了三个过程来处理。~。~ 这真是Hard中最水的一题了。 没有之一。 憋不出什么话说了。 既然我不知道说什么, 那我也就不知道在这里写些什么了。就这样吧。
The End.
相关文章推荐
- leetcode题解-57. Insert Interval
- leetcode 57. Insert Interval
- leetcode 57. Insert Interval
- leetcode-57. Insert Interval
- LeetCode 57. Insert Interval
- leetcode 57. Insert Interval
- leetcode - 57. Insert Interval
- [Leetcode] 57. Insert Interval
- LeetCode 436. Find Right Interval 题解(C++)
- LeetCode-----57. Insert Interval(数组插入并重新合并)
- [LeetCode]题解(python):057-Insert Interval
- LeetCode 57. Insert Interval/56. Merge Intervals
- leetcode 57. Insert Interval
- Leetcode 56. Merge Intervals && 57. Insert Interval(Hard)
- leetcode hard模式专杀之57. Insert Interval
- Leetcode 57. Insert Interval
- leetcode 57. Insert Interval
- [Leetcode] 57. Insert Interval
- [Leetcode]57. Insert Interval
- [leetcode]57. Insert Interval(Java)