小念子

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。

然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。

你需要计算完成所有任务所需要的最短时间。

 

 

 解答

方法一:

使用最大值堆,保存剩余不同类型的任务数量,在堆不为空的情况下,处理堆中的任务。由于间隔n,因此每轮处理n+1次。

①每次,若堆不空,堆顶元素>1,则将该元素-1放入临时list,并删除该堆顶元素

                             堆顶元素<=1,则删除该堆顶元素

②轮数i++,时间++

③重新将临时list中的元素加入queue

④如果queue为空,并且临时list为空,直接返回times,否则,继续循环处理queue

    public int leastInterval(char[] tasks, int n) {
        int times = 0;
        int[] count = new int[26];
        for (char ch : tasks) {
            count[ch - 'A']++;
        }
        PriorityQueue<Integer> queue = new PriorityQueue<Integer>(26, Collections.reverseOrder()); // 最大值堆
        for (int value : count) {
            if (value > 0) {
                queue.add(value);
            }
        }
        while(!queue.isEmpty()) {
            List<Integer> tempList = new ArrayList<Integer>(); // 临时list,存储处理过的任务
            // 由于间隔是n,所以每一轮处理n+1种任务,任务种类数没有n+1就放空
            int i = 0;
            while(i <= n) {
                if (!queue.isEmpty()) {
                    if (queue.peek() > 1) {
                        tempList.add(queue.poll() - 1);
                    } else {
                        queue.poll();
                    }
                }
                i++;
                times++;
                if (tempList.size() == 0 && queue.isEmpty()) {
                    return times;
                }
            }
            for (int value : tempList) {
                queue.add(value);
            }
        }
        return times;
    }

方法二:

找规律取巧

    public int leastInterval(char[] tasks, int n) {
        int times = 0;
        int[] count = new int[26];
        for (char ch : tasks) {
            count[ch - 'A']++;
        }
        int max = 0; // 出现最多次的任务次数
        for (int value : count) {
            if (value > max) {
                max = value;
            }
        }
        int countForMax = 0; // 出现最多次的任务种类
        for (int value : count) {
            if (value == max) {
                countForMax ++;
            }
        }
        // (max - 1)处理的轮数,-1是因为多出来这个任务之后不会有间隔,后面再统计
        // (n + 1)表示每轮处理需要的时间
        // 任务的任务countForMax直接加上即可,因为这些任务之后不需要加放空的时间
        times = (max - 1) * (n + 1) + countForMax; 
        return times < tasks.length ? tasks.length : times;
    }

 

posted on 2020-11-16 21:07  小念子  阅读(140)  评论(0编辑  收藏  举报