57. 插入区间(中等)
Blind 75 › 57. 插入区间(中等) (第 1 章)
题目
给你一个已经按左端点升序排好、且两两不重叠的区间列表,例如 [[2,4],[6,8]];再给一个新区间 [5,7]。把新区间插进去,如果它与原区间有交点,就把它们合并成一个区间;插完后仍需保持左端点升序、且两两不重叠。
两个区间只要至少共享一个点,就认为重叠——包括只共享端点。例如 [1,4] 和 [4,6] 重叠,应合并成 [1,6]。
自造示例:[[2,4],[6,8]] 插入 [3,7] → [[2,8]];再如 [[1,2],[6,9]] 插入 [3,5] → [[1,2],[3,5],[6,9]]。
约束:区间个数 0 ~ 104;每个区间含两个整数,0 ≤ start ≤ end ≤ 105;原列表已按左端点升序且无重叠;新区间长度同样为 2。不要求原地修改,可新建数组返回。
思路
一句话:因为原列表已经有序,每个原区间相对新区间只可能落在三种位置之一——左边、重叠、右边;一次线性扫描分三段处理即可。
先想最直白的做法:把新区间塞进原列表,再按左端点排序,然后从头到尾合并重叠区间。这个思路完全正确,但浪费了题目给的“已经按左端点排好序”这个条件,多花一次 O(n log n) 的排序。
关键观察:原区间按左端点递增,所以相对新区间而言,会出现一个连续前缀“完全在左”、一个连续中段“可能与新区间重叠”、一个连续后缀“完全在右”。我们只需要:
- 左边:
原区间右端点 < 新区间左端点,不可能碰,直接保留; - 重叠:
原区间左端点 ≤ 新区间右端点,合并并不断扩展新区间; - 右边:从某个位置开始全部在原新区间之后,直接照抄。
重叠区间的“合并”就是不断取左右边界的最小值和最大值。因为一旦进入重叠段,后续的区间也可能连着叠,所以要把中段一次吃完再放入答案。
解法
用指针 i 从左往右扫一遍,ans 存结果:
- 先把“完全在新区间左边”的区间加入答案。
- 再处理所有“与新区间重叠”的区间,持续更新合并后的
[start, end]。 - 把合并后的新区间加入答案。
- 最后把“完全在新区间右边”的区间全部加入答案。
以 [[2,4],[6,8],[10,12]] 插入 [5,11] 为例:
| 当前原区间 | 与新区间关系 | 操作 | 答案 |
|---|---|---|---|
| [2,4] | 4 < 5,完全在左 | 直接保留 | [[2,4]] |
| [6,8] | 6 ≤ 11,重叠 | 合并成 [5,11] | [[2,4]] |
| [10,12] | 10 ≤ 11,仍重叠 | 合并成 [5,12] | [[2,4]] |
| — | 扫描结束 | 放入 [5,12] | [[2,4],[5,12]] |
下图把上面 4 个步骤串成流程,并逐步演示:


还没有评论,来说两句?