题目描述
思路解析动画文字版
三段式:左边不沾的先收 → 中间重叠的全吃进新区间 → 右边不沾的,先放合并好的新区间再收尾。下面一帧帧套。
准备插入新区间 [4,8]。结果列表现在是空的,指针还没出发,下面逐格判断。
指针走到第 0 个区间 [1,2],准备和当前新区间 [4,8] 比较位置关系。
它整个在新区间左边,互不相干,归第一类。
第一类:不沾边,原样收进结果(标绿的就是已收进结果的)。新区间还没动。
指针走到第 1 个区间 [3,5],准备和当前新区间 [4,8] 比较位置关系。
它和新区间挨上了,要被吃进去,归第二类。
第二类:把 [3,5] 吃进新区间(标红表示正被合并)。新区间左端取更小、右端取更大,变成 [3,8],越合越大。
指针走到第 2 个区间 [6,7],准备和当前新区间 [3,8] 比较位置关系。
它和新区间挨上了,要被吃进去,归第二类。
第二类:把 [6,7] 吃进新区间(标红表示正被合并)。新区间左端取更小、右端取更大,变成 [3,8],越合越大。
指针走到第 3 个区间 [8,10],准备和当前新区间 [3,8] 比较位置关系。
它和新区间挨上了,要被吃进去,归第二类。
第二类:把 [8,10] 吃进新区间(标红表示正被合并)。新区间左端取更小、右端取更大,变成 [3,10],越合越大。
指针走到第 4 个区间 [12,16],准备和当前新区间 [3,10] 比较位置关系。
它整个在新区间右边,合并阶段到此结束,归第三类。
遇到右边不沾的区间,说明新区间已经合完了。先把合并好的 [3,10] 放进结果,再继续收剩下的。
第三类:它在新区间右边,原样收进结果(标绿)。后面的也都这样收完。
指针走到第 5 个区间 [18,20],准备和当前新区间 [3,10] 比较位置关系。
它整个在新区间右边,合并阶段到此结束,归第三类。
第三类:它在新区间右边,原样收进结果(标绿)。后面的也都这样收完。
指针走到第 6 个区间 [22,25],准备和当前新区间 [3,10] 比较位置关系。
它整个在新区间右边,合并阶段到此结束,归第三类。
第三类:它在新区间右边,原样收进结果(标绿)。后面的也都这样收完。
扫描结束。最终答案是 [1,2] [3,10] [12,16] [18,20] [22,25],中间那串被 [4,8] 串成了 [3,10]。
三个高频追问:为何不用排序、不重叠时怎么插、以及合并取 min/max 的道理。
参考代码
def insert(intervals, newInterval): res, i, n = [], 0, len(intervals) # 1) 左边不重叠的:原样收 while i < n and intervals[i][1] < newInterval[0]: res.append(intervals[i]); i += 1 # 2) 重叠的:吃进 newInterval while i < n and intervals[i][0] <= newInterval[1]: newInterval[0] = min(newInterval[0], intervals[i][0]) newInterval[1] = max(newInterval[1], intervals[i][1]) i += 1 res.append(newInterval) # 3) 右边不重叠的:原样收 while i < n: res.append(intervals[i]); i += 1 return res复杂度
- 时间:O(n),三个 while 合起来恰好把每个区间访问一次,n 是原区间个数
- 空间:O(n),除返回的结果列表外只用常数变量;结果本身最多装 n+1 个区间
易错点
面试追问把动画讲成自己的话
追问为什么可以一趟线性扫描,而不用排序?
追问如果新区间和所有原区间都不重叠会怎样?
追问合并那一步为什么左端取 min、右端取 max?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
合并区间
LeetCode 56 · 中等 · 沿着 区间 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题