题目:
给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals,其中 intervals[i] = [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval = [start, end] 表示另一个区间的开始和结束。
在 intervals 中插入区间 newInterval,使得 intervals 依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。
返回插入之后的 intervals。
注意 你不需要原地修改 intervals。你可以创建一个新数组然后返回它。
示例 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] 重叠。
提示:
-
0 <= intervals.length <= 104
-
intervals[i].length == 2
-
0 <= starti <= endi <= 105
-
intervals 根据 starti 按 升序 排列
-
newInterval.length == 2
-
0 <= start <= end <= 105
思路如下:
此题与56题无限近似。我们把新的区间加入,然后按照左边界排序。因为题目交代起始端点是有序排列的,我们可以使用二分插入到数组中。最后则是56题的解法遍历数组合并区间。
题解如下:
class Solution:
def insert(self, intervals, newInterval):
"""
:type: intervals: List[List[int]], newInterval: List[int]
:rtype: List[List[int]]
"""
# 使用bisect.insort插入新区间,保持按起始端点排序
bisect.insort(intervals, newInterval)
#56题解法,合并区间
ans = []
for interval in intervals:
# 如果结果列表不为空且当前区间可以合并
if ans and interval[0] <= ans[-1][1]:
# 合并区间,更新结束点为较大者
ans[-1][1] = max(ans[-1][1], interval[1])
else:
# 否则直接加入结果列表
ans.append(interval)
return ans
时间复杂度为O(n),空间复杂度为O(n),其中 n 是区间的数量。
注意事项:
1.为什么 bisect.insort 默认基于起始端点排序?
Python 的默认比较规则:当比较两个列表(如 [a, b] 和 [c, d])时,Python 会先比较第一个元素 a 和 c,若相等再比较第二个元素 b 和 d。因此,bisect.insort 在插入 newInterval 时,会按起始端点(第一个元素)排序。
2.如何改为基于终止端点排序?
bisect.insort(intervals, newInterval, key=lambda x: x[1])
3.python自带的bisect库(标准库)
例子:a = [3, 5, 6, 10] b=6
-
bisect.bisect(a,b) #第一个bisect是库名,第二个bisect是模块名
-
bisect和insort的默认情况均是排在右边
-
bisect.bisect_left(a,b)排在左边
-
bisect.bisect(a,b)是获得插入位置,bisect.insort是直接二分插入