57. 插入区间
题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/insert-interval/
题目
给出一个*无重叠的 ,*按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
示例 1:
输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]
示例 2:
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。
**注意:**输入类型已在 2019 年 4 月 15 日更改。请重置为默认代码定义以获取新的方法签名。
解题思路
先提一下站内的 56. 合并区间,第 56 题中合并区间的思想可以借鉴,有兴趣的话也可以先尝试下 56 题。
看回这道题,先看题目的给出的线索及要求:
线索:
- 给定的区间列表已经按照区间起始端点排序,且无重叠。
要求:
- 给定一个新的区间,插入原有的区间列表中,并且保证列表中的区间仍有序且不重叠。(可合并区间)
现在根据上述的线索及要求,结合示例 2 看下。新区间与原区间列表中的区间存在这样关系:
- 原区间列表中的区间,右端的值小于新区间左端的值。(如示例 2 中的区间
[1, 2]
右端值 2 小于新区间[4, 8]
左端值 4); - 原区间列表中的区间,与新区间重叠。(如示例 2 中的区间
[3,5],[6,7],[8,10]
,与新区间[4,8]
重叠); - 原区间列表中的区间,左端的值大于新区间右端的值。(如示例 2 中的区间
[12, 16]
左端的值 12 大于新区间[4, 8]
右端值 8)。
根据上面的关系,这里说下具体的处理方法:
- 第一种情况,我们将右端的值小于新区间左端的值的区间,加到结果列表中;
- 第二种情况,这里,我们考虑将其合并。其中这里合并后区间的左端值取原两个区间的较小值,而右端值取两区间中的较大值。(例如示例 2 中,重叠部分合并后的区间的左端值为 3,右端值取的是 10)最后添加到结果列表中;
- 第三种情况,这种情况与第一种情况类似,直接将左端的值大于新区间右端的值的区间加到结果列表中。
具体代码实现如下。
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
n = len(intervals)
ans = []
i = 0
# 遍历原区间列表
# 先考虑原区间列表中的区间,右端的值小于新区间左端的值的情况
while i < n and intervals[i][1] < newInterval[0]:
ans.append(intervals[i])
# 循环查找,直至发现重叠部分
i += 1
# 处理重叠部分
# 这里还有个隐式条件,也就是上面条件不成立,
# 此时 intervals[i][1] >= newInterval[0]
while i < n and intervals[i][0] <= newInterval[1]:
# 进行合并,左端值取原两个区间的较小值,而右端值取两区间中的较大值
# 这里直接将合并的区间更新到 newInterval 上
newInterval[0] = min(intervals[i][0], newInterval[0])
newInterval[1] = max(intervals[i][1], newInterval[1])
i += 1
# 合并之后,加到结果列表中
ans.append([newInterval[0], newInterval[1]])
# 最后处理原区间列表中的区间,左端的值大于新区间右端的值的情况
while i < n and intervals[i][0] > newInterval[1]:
ans.append(intervals[i])
i += 1
return ans
欢迎关注
公众号 【书所集录】
如有错误,烦请指出,欢迎指点交流。