往期博客:
目录
题目
给你一个 无重叠的 ,按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
题目分析:
已知:无重叠有序区间列表
目的:插入新区间
要求:区间仍有序无重叠
示例
示例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] 重叠。
示例3
输入:intervals = [], newInterval = [5,7] 输出:[[5,7]]
示例4
输入:intervals = [[1,5]], newInterval = [2,3] 输出:[[1,5]]
示例5
输入:intervals = [[1,5]], newInterval = [2,7] 输出:[[1,7]]
解析
排序法
这道题的排序法和Leetcode56合并区间的排序法思路是一样的,在Leetcode56合并区间中整个区间列表都是无序的所徐娇进行一个排序对的过程,将排序好的列表中的区间进行两两判断,看是否有重叠,而在本题中已给的区间列表是有序的,但是加入新的一个区间后,列表可能就无序了,所以仍需要一个排序的过程。
根据示例详细分析。
对于示例1中,原始区间列表为[[1,3],[6,9]],其中[1,3],[6,9]两个区间是有序的,因为第一个区间的end小于第二个区间的start,即3<6,又给了一个新区间[2,5],我们可以先把新区间[2,5]插入到列表的末尾
新列表是一个无序列表,将新列表进行排序,排序是按每个区间的start进行排的
将排序后的列表中的区间两两进行判断,判断是否有重叠区域,判断原则是如果前一个区间的end大于后一个区间的start,则说明两个区间有重叠区域
- 将有重叠区域的两个区间合并成一个区间,合并原则是将前一个区间的start作为新区间的start,选取两个区间中较大的end作为新区间的end
最后输出有序无重叠的新列表
贪心法
贪心算法的思想就是每一步都选择最佳的解决方法。
对于示例1区间[[1,3],[6,9]]和[2,5],可以从下面3步进行考虑
1. 如果区间的开始时间start小于新区间[2,5]的开始时间
则直接将该区间放到结果集result中
2. 如果此时列表中已经没有再比新区间开始时间小的区间,将新区间放到结果集中
插入新区间时考虑新区间是否要和前一个区间进行合并:
如果previous[end] <= new[start],则需要合并
如果previous[end] > new[start],则不需要合并
3. 把最后剩余的区间(开始时间小于新区间开始时间的区间)放到结果集中
代码
排序法
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
result = [] # 建立空列表存放结果
# 边界条件,当原始列表中无区间时直接将新区间添加到结果中返回
if len(intervals) == 0:
result.append(newInterval)
return result
intervals.append(newInterval) # 将新区间加入到元列表的末尾
intervals.sort(key=lambda x:x[0]) # 按每个区间的start进行排序
for interval in intervals:
if len(result) == 0 or result[-1][1] < interval[0]:
result.append(interval) # 如果结果中此时为空或者结果中的最后一个区间和当前区间无重叠则直接加入到结果列表中的末尾
else:
result[-1][1] = max(result[-1][1], interval[1]) # 否则重叠后的区间的end为两个区间中较大的end
return result
贪心法
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
result = [] # 建立空列表存放结果
index = 0
# step1:将开始时间相遇新区间开始时间的区间加入结果集
for interval in intervals:
if interval[0] < newInterval[0]:
result.append(interval)
index += 1
else:
break
# step2:将新区间加入结果集中,分情况考虑是否需要合并
if len(result) == 0 or result[-1][1] < newInterval[0]:
result.append(newInterval)
else:
result[-1][1] = max(result[-1][1], newInterval[1])
# step3:将剩余的区间加入到结果集中
for i in range(index, len(intervals)):
if result[-1][1] < intervals[i][0]:
result.append(intervals[i])
else:
result[-1][1] = max(result[-1][1], intervals[i][1])
return result