不同区间的并集和交集

可能标题没有说清楚,如下:

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 []

 

posted @ 2021-12-13 22:18  r1-12king  阅读(1035)  评论(0编辑  收藏  举报