今天我尝试刷题,小M的多任务下载器挑战 问题描述 小M的程序设计大作业是编写一个多任务下载器。在实现过程中,他遇到了一个问题:在一次下载过程中,总共有N个任务,每个任务会在第x秒开始,并持续y秒。小M需要知道,在同一时刻,最多有多少个任务正在同时下载,也就是计算出任务的最高并发数。为了解决这个问题,我们可以使用"扫描线"算法,这是处理时间区间重叠的常用方法。核心思路是对任务的开始和结束时刻分别记录事件,并对这些事件进行排序和处理,以计算在任意时刻的并发任务数。
解决方案步骤
-
记录事件:
- 对每个任务,将开始时刻
x视为“+1”事件(表示任务开始,活跃任务数增加)。 - 将结束时刻
x + y视为“-1”事件(表示任务结束,活跃任务数减少)。
- 对每个任务,将开始时刻
-
排序事件:
- 将所有事件按照时间顺序排序。如果时间相同,优先处理“+1”事件(因为任务在开始时刻应立即计入并发数)。
-
扫描并计算并发数:
- 遍历排序后的事件,累加“+1”事件并减去“-1”事件,同时维护当前的最大并发数。
代码实现
def solution(n, array):
events = []
# Step 1: Create events for start and end times
for start, duration in array:
events.append((start, 1)) # Task starts
events.append((start + duration, -1)) # Task ends
# Step 2: Sort events; if time is the same, end events come after start events
events.sort(key=lambda x: (x[0], x[1]))
# Step 3: Track the max concurrency level
max_concurrent = 0
current_concurrent = 0
# Step 4: Process each event
for _, event in events:
current_concurrent += event
max_concurrent = max(max_concurrent, current_concurrent)
return max_concurrent
if __name__ == "__main__":
# Test cases
print(solution(2, [[1, 2], [2, 3]]) == 2) # Output should be 2
print(solution(4, [[1, 2], [2, 3], [3, 5], [4, 3]]) == 3) # Output should be 3
print(solution(5, [[1, 3], [3, 4], [2, 2], [6, 5], [5, 3]]) == 3) # Output should be 3
代码解析
-
事件生成:
- 对于每个任务,生成两个事件:开始时刻和结束时刻。
-
事件排序:
- 按时间先后排序。如果两事件时刻相同,则“+1”事件优先处理,以确保任务在该时刻即计入并发数。
-
并发数统计:
- 遍历事件时,实时更新当前的活跃任务数并记录最大值。
复杂度分析
- 时间复杂度:(O(n \log n)),因为我们对事件进行排序。
- 空间复杂度:(O(n)),需要存储事件列表。
测试案例
- 样例 1:
n = 2, array = [[1, 2], [2, 3]],输出应为2。 - 样例 2:
n = 4, array = [[1, 2], [2, 3], [3, 5], [4, 3]],输出应为3。 - 样例 3:
n = 5, array = [[1, 3], [3, 4], [2, 2], [6, 5], [5, 3]],输出应为3。
此解决方案能够高效处理任务的最高并发数,适合解决类似区间重叠问题。