问题分析
我们需要解决的是 任务并发问题,即在同一时间段内,最多有多少个任务同时进行。可以将任务的时间范围视为一个区间问题,通过记录开始时间和结束时间来计算最高并发数。
思路
-
将任务转化为事件:
- 每个任务的开始时间可以看作是一个事件,表示“一个任务开始”。
- 每个任务的结束时间可以看作是一个事件,表示“一个任务结束”。
-
记录事件:
- 将所有任务的开始时间和结束时间记录为事件。
- 对于每个任务的结束时间,需要注意的是它在
开始时间 + 持续时间的下一秒结束,因此结束时间为x + y。
-
事件排序:
- 按时间对事件排序。如果时间相同,则优先处理“任务结束”的事件(先结束再开始,这样能避免冲突)。
-
计算并发数:
- 遍历排序后的事件数组,维护一个计数器记录当前同时进行的任务数。
- 遇到“任务开始”事件,计数器加1;遇到“任务结束”事件,计数器减1。
- 在整个遍历过程中,记录计数器的最大值,即为最高并发数。
代码实现
def solution(n, array):
# 记录任务的开始和结束事件
events = []
for x, y in array:
events.append((x, 1)) # 任务开始
events.append((x + y, -1)) # 任务结束
# 对事件按时间排序;同一时间,结束事件优先
events.sort(key=lambda event: (event[0], event[1]))
# 计算并发数
concurrent = 0
max_concurrent = 0
for _, event_type in events:
concurrent += event_type # +1 表示任务开始,-1 表示任务结束
max_concurrent = max(max_concurrent, concurrent)
return max_concurrent
if __name__ == "__main__":
# 测试用例
print(solution(2, [[1, 2], [2, 3]]) == 2) # 示例 1
print(solution(4, [[1, 2], [2, 3], [3, 5], [4, 3]]) == 3) # 示例 2
print(solution(5, [[1, 3], [3, 4], [2, 2], [6, 5], [5, 3]]) == 3) # 示例 3
代码详解
-
事件生成:
- 遍历任务列表
array,将每个任务的开始时间和结束时间分别加入events列表。
- 遍历任务列表
-
事件排序:
- 按时间排序
events,如果时间相同,优先处理任务结束事件。 - 例如,任务
[[1, 2], [2, 3]]产生的事件为:[(1, 1), (3, -1), (2, 1), (5, -1)],排序后为:[(1, 1), (2, 1), (3, -1), (5, -1)]。
- 按时间排序
-
并发计算:
- 遍历排序后的
events,根据事件类型更新当前并发任务数。 - 同时记录最大并发数
max_concurrent。
- 遍历排序后的
复杂度分析
-
时间复杂度:
- 生成事件的复杂度为 。
- 排序事件的复杂度为 。
- 遍历事件的复杂度为 。
- 总体时间复杂度为 。
-
空间复杂度:
- 额外存储事件数组,复杂度为 。
测试结果
示例 1
solution(2, [[1, 2], [2, 3]])
# 输出: 2
示例 2
solution(4, [[1, 2], [2, 3], [3, 5], [4, 3]])
# 输出: 3
示例 3
solution(5, [[1, 3], [3, 4], [2, 2], [6, 5], [5, 3]])
# 输出: 3
总结
- 本解法通过事件排序和计数实现了对最高并发数的高效计算。
- 排序解决了任务重叠问题,遍历过程记录并发数变化,最终得出最高并发数。