青训营刷题日记06 | 豆包MarsCode AI 刷题

106 阅读2分钟

今天我尝试刷题,小M的多任务下载器挑战 问题描述 小M的程序设计大作业是编写一个多任务下载器。在实现过程中,他遇到了一个问题:在一次下载过程中,总共有N个任务,每个任务会在第x秒开始,并持续y秒。小M需要知道,在同一时刻,最多有多少个任务正在同时下载,也就是计算出任务的最高并发数。为了解决这个问题,我们可以使用"扫描线"算法,这是处理时间区间重叠的常用方法。核心思路是对任务的开始和结束时刻分别记录事件,并对这些事件进行排序和处理,以计算在任意时刻的并发任务数。

解决方案步骤

  1. 记录事件

    • 对每个任务,将开始时刻 x 视为“+1”事件(表示任务开始,活跃任务数增加)。
    • 将结束时刻 x + y 视为“-1”事件(表示任务结束,活跃任务数减少)。
  2. 排序事件

    • 将所有事件按照时间顺序排序。如果时间相同,优先处理“+1”事件(因为任务在开始时刻应立即计入并发数)。
  3. 扫描并计算并发数

    • 遍历排序后的事件,累加“+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. 事件生成

    • 对于每个任务,生成两个事件:开始时刻和结束时刻。
  2. 事件排序

    • 按时间先后排序。如果两事件时刻相同,则“+1”事件优先处理,以确保任务在该时刻即计入并发数。
  3. 并发数统计

    • 遍历事件时,实时更新当前的活跃任务数并记录最大值。

复杂度分析

  • 时间复杂度:(O(n \log n)),因为我们对事件进行排序。
  • 空间复杂度:(O(n)),需要存储事件列表。

测试案例

  1. 样例 1n = 2, array = [[1, 2], [2, 3]],输出应为 2
  2. 样例 2n = 4, array = [[1, 2], [2, 3], [3, 5], [4, 3]],输出应为 3
  3. 样例 3n = 5, array = [[1, 3], [3, 4], [2, 2], [6, 5], [5, 3]],输出应为 3

此解决方案能够高效处理任务的最高并发数,适合解决类似区间重叠问题。