Java题解 小M的多任务下载器挑战 | 豆包MarsCode AI刷题

82 阅读3分钟

小M的多任务下载器挑战

问题描述

小M的程序设计大作业是编写一个多任务下载器。在实现过程中,他遇到了一个问题:在一次下载过程中,总共有N个任务,每个任务会在第x秒开始,并持续y秒。小M需要知道,在同一时刻,最多有多少个任务正在同时下载,也就是计算出任务的最高并发数。

解题思路:

我们首先将问题建模,把时间看成一个坐标轴,一个任务就相当于一条覆盖[x[i],x[i]+y[i]1][x[i],x[i]+y[i]-1]的直线,在代码中,就可以用一个数组表示,数组初始元素全为0,加入一个任务就是把[x[i],x[i]+y[i]1][x[i],x[i]+y[i]-1]对应的元素加1,然后遍历数组,统计哪个下标的值最大即可,这样做的话需要两重循环,外层循环遍历所有的任务,内层循环遍历任务影响坐标,复杂度是O(N2)O(N^2),对于数据范围较大的情况就不适用了。我们考虑使用差分数组降低复杂度,差分数组形式化地讲就是对于一个数组a,我们新建一个数组b,其中b[i]=a[i]a[i1]b[i]=a[i]-a[i-1]。将差分数组用于这道题目,对于单个任务i,任务的持续时间为[x[i],x[i]+y[i]1][x[i],x[i]+y[i]-1],那么我们可以将差分数组的x[i]x[i]下标的值加1,x[i]+y[i]x[i]+y[i]下标的值减一,最后只需要遍历一遍差分数组,每次加上当前数组元素,与答案取最大值即可。由于题目没有给出具体的数据范围,为了防止超出数组最大可分配空间,需要使用离散化对坐标进行映射处理。(不用离散化能不能通过我没有进行实验...)离散化的思路是将坐标从小到大进行排序并去重,然后原来的坐标一一对应现在所处的位置,例如[1,1,32,15,7][1,1,32,15,7],离散化后的原数组对应的新值是[1,1,4,3,2][1,1,4,3,2],这样就不用担心出现1e9这样的大坐标导致数组无法开这么大。具体实现可以参考下面的代码。

代码:

import java.util.*;

public class Main {

    public static int solution(int n, int[][] array) {
        // Edit your code here
        TreeSet<Integer> set = new TreeSet<>();
        for (int i = 0; i < n; ++i) {
            set.add(array[i][0]);
            set.add(array[i][0] + array[i][1]);
        }
        Map<Integer, Integer> map = new HashMap<>();
        int cnt = 0;
        for (int i : set)
            map.put(i, ++cnt);
        int[] a = new int[cnt + 10];
        for (int i = 0; i < n; ++i) {
            a[map.get(array[i][0])]++;
            a[map.get(array[i][0] + array[i][1])]--;
        }
        int now = 0, ans = 0;
        for (int i = 1; i <= cnt; ++i) {
            now += a[i];
            ans = Math.max(ans, now);
        }
        return ans;
    }

    public static void main(String[] args) {
        // Add your test cases here
        System.out.println(solution(2, new int[][]{{1, 2}, {2, 3}}) == 2);
        System.out.println(solution(4, new int[][]{{1, 2}, {2, 3}, {3, 5}, {4, 3}}) == 3);
    }
}

代码解析:

使用TreeSet和HashMap进行离散化操作,由于TreeSet中存储的元素是有序且唯一的,所以可以很方便地进行离散化操作,将所有坐标放入TreeSet后,直接从小到大遍历并把坐标对应离散化后的新值记录到HashMap中,最后在差分数组上进行遍历并更新答案,注意在离散化后坐标都要使用map.get()方法得到对应的新值。