小M的多任务下载器挑战
题目分析
需要计算在同一时刻最多有多少个任务正在同时下载。每个任务有一个开始时间和持续时间,这意味着每个任务有一个开始时刻和一个结束时刻。
算法步骤:
-
事件提取:
- 对于每个任务,提取其开始时间和结束时间,并分别标记为“开始事件”和“结束事件”。
- 将所有事件存储在一个数组中。
-
事件排序:
- 对事件数组进行排序,首先按时间排序,如果时间相同,则结束事件优先于开始事件。
-
扫描事件:
- 遍历排序后的事件数组,使用一个变量记录当前并发任务数。
- 遇到开始事件时,增加并发任务数;遇到结束事件时,减少并发任务数。
- 在遍历过程中,记录并发任务数的最大值。
-
事件提取:
- 对于每个任务,提取其开始时间和结束时间,并分别标记为“开始事件”和“结束事件”。
- 将所有事件存储在一个数组中。
-
事件排序:
- 对事件数组进行排序,首先按时间排序,如果时间相同,则结束事件优先于开始事件。
-
扫描事件:
- 遍历排序后的事件数组,使用一个变量记录当前并发任务数。
- 遇到开始事件时,增加并发任务数;遇到结束事件时,减少并发任务数。
- 在遍历过程中,记录并发任务数的最大值。
代码+分析
事件数组的构造:
事件数组用于记录任务的开始和结束时间。每个任务会生成两个事件:
- 一个是开始时间事件,表示任务开始。
- 一个是结束时间事件,表示任务结束。
任务的结束时间是通过 start + duration 来计算的。
排序事件:
为了方便计算并发数,我们需要对事件进行排序。排序的规则是:
- 按照时间升序排序。
- 如果时间相同,则结束事件(标记为
-1)应该排在开始事件(标记为1)之前。这样可以避免同一时刻多个任务开始和结束时并发数的计算问题。
计算最大并发数:
- 我们通过遍历排序后的事件数组,维护一个当前并发数(
currentConcurrent),每遇到一个开始事件,当前并发数增加;遇到一个结束事件,当前并发数减少。 - 在每次更新当前并发数时,记录最大并发数。
复杂度分析:
- 时间复杂度:排序事件数组的时间复杂度为
O(n log n),其中n是任务的数量。遍历事件数组的时间复杂度为O(n)。因此,总的时间复杂度为O(n log n)。 - 空间复杂度:需要额外的
O(n)空间来存储事件数组。