不同区间的并集和交集
可能标题没有说清楚,如下:
1.求区间的并
例如:56. 合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
解答:
如果我们按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的。如下图所示,标记为蓝色、黄色和绿色的区间分别可以合并成一个大区间,它们在排完序的列表中是连续的:
代码写的不简洁,大概知道什么意思就行:
1 class Solution(object): 2 def merge(self, intervals): 3 """ 4 :type intervals: List[List[int]] 5 :rtype: List[List[int]] 6 """ 7 interval = sorted(intervals) 8 data = [] 9 n = len(interval) 10 if n <= 1: 11 return interval 12 i = 0 13 r = [interval[0][0], interval[0][1]] 14 while i < n: 15 if i + 1 < n and r[1] < interval[i + 1][0]: 16 data.append([r[0], r[1]]) 17 i += 1 18 r[0] = interval[i][0] 19 r[1] = interval[i][1] 20 elif i + 1 < n and r[1] < interval[i + 1][1]: 21 r[1] = interval[i + 1][1] 22 i += 1 23 else: 24 i += 1 25 26 data.append(r) 27 return data
2、求区间的交集
例如:
房屋租赁处计划安排房东和租赁者关于房屋租赁进行见面沟通,目前已有房东和租赁者各自的空闲时间表:time1 和 time2,以及本次沟通的预期持续时间 period,请帮助他们安排最早的合适「沟通时间」,若没有合适的「沟通时间」,则返回一个空数组。
注意:
「沟通时间」是房东和租赁者都有空参加,并且持续时间能够满足预期时间 period 的 时间间隔
「空闲时间」的格式是 [start, end],由开始时间 start 和结束时间 end 组成,表示从 start 开始,到 end 结束
输入用例保证:同一个人的空闲时间无交叠的情况,即,对于同一个人的两个空闲时间 [start1, end1] 和 [start2, end2],要么 start1 > end2,要么 start2 > end1。
示例 1:
输入:time1 = [[0,20],[40,80],[120,200]], time2 = [[10,20],[50,100]], period = 20
输出:[50,70]
解释:如图所示,房东和租赁者均空闲且持续时间为 20 的最早时间间隔为 [50,70]
示例 2:
输入:time1 = [[10,20],[50,100]], time2 = [[35,41]], period = 5
输出:[]
解释:由于无双方均空闲的时间,因此返回空数组
思路与算法
题目保证了同一个人的空闲时间不会出现交叠的情况,于是先把两个人的空闲时间表按照开始时间从小到大排序。
排序后的时间表假设如下:
slots1 = [[10, 50], [60, 120], [140, 210]]
slots2 = [[0, 15], [60, 70]]
定义一个变量 idx1 用于遍历 slots1,idx2 用于遍历 slots2。
假设 duration 为 8:
1、对于初始的 [10, 50] 和 [0, 15] ,看出开始最早的是客户 2,结束最晚的是客户 1,交集就是 [10, 15] 发现小于 duration,因为结束最晚的是客户 1,于是客户 1 的索引不动,因为可能交集还是在客户 1 当前的 [10, 50] 区间内,让 idx2++;
2、此时两个时间表为 [10, 50] 和 [60, 70],没有交集,应该继续找下一个时间表,因为此时结束时间最晚的是客户 2,可能的目标交集会在 [60, 70] ,于是让 idx1++;
3、此时两个时间表为 [60, 120] 和 [60, 70],开始最晚的时间是 60,结束最早的时间是 70,满足 duration,于是返回 [最晚开始时间, 最晚开始时间+duration]
1 class Solution(object): 2 def minAvailableDuration(self, time1, time2, duration): 3 # 给两个时间段排序 4 time1 = sorted(time1) 5 time2 = sorted(time2) 6 idx1, idx2 = 0, 0 7 # 遍历两个时间段 8 while idx1 < len(time1) and idx2 < len(time2): 9 # 遍历到的时间段的末位置 10 ed1 = time1[idx1][1] 11 ed2 = time2[idx2][1] 12 st = max(time1[idx1][0], time2[idx2][0]) # 最晚开始时间 13 if ed1 > ed2: # 1的时间比较宽 14 if ed2 - st >= duration: 15 return [st, st + duration] 16 idx2 += 1 17 else: # 2的时间比较宽 18 if ed1 - st >= duration: 19 return [st, st + duration] 20 idx1 += 1 21 22 return []