zoukankan      html  css  js  c++  java
  • 贪心-优先队列-模拟-任务调度器

    2020-03-10 17:22:21

    问题描述:

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

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

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

    示例 1:

    输入: tasks = ["A","A","A","B","B","B"], n = 2
    输出: 8
    执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B.

    注:

    任务的总个数为 [1, 10000]。
    n 的取值范围为 [0, 100]。

    问题求解:

    解法一:贪心

    从数据规模可以看出时间复杂度应该是O(n) / O(nlogn)。很容易想到的是要先将频率计算出来,并且按照频率进行排序,频率最高的字符至少会占用(freq_max - 1) * (n + 1) + 1个时间周期。

    如果有k个频率均为最高,那么上述的公式就变成了(freq_max - 1) * (n + 1) + k,在这种情况下,低频率的字符完全放入了中间的空当中,甚至还会有盈余。

    那么还有一种情况就是,中间的空档并不够放置所有剩余的字符,那么此时最终的解就是len(tasks),因为剩余的字符可以任意的插入不同slot的末尾,并且保证空闲是足够的。

    算法时间复杂度:O(nlogn)

        public int leastInterval(char[] tasks, int k) {
            int n = tasks.length;
            int[] freq = new int[26];
            for (char c : tasks) freq[c - 'A'] += 1;
            Arrays.sort(freq);
            int idx = 25;
            while (idx >= 0 && freq[idx] == freq[25]) idx -= 1;
            int common = 25 - (idx + 1) + 1;
            return Math.max(n, (freq[25] - 1) * (k + 1) + common);
        }
    

      

    解法二:优先队列

    本题除了上述的贪心解法,还可以使用优先队列去模拟结果,使用优先队列的解更加直观。我们每次从队列中取k + 1个最多的任务去做,全部任务都执行完成即可。

    时间复杂度:O(time) 和最终的任务序列长度有关。

        public int leastInterval(char[] tasks, int k) {
            int n = tasks.length;
            int[] freq = new int[26];
            for (char c : tasks) freq[c - 'A'] += 1;
            PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
            for (int i = 0; i < 26; i++) if (freq[i] != 0) pq.add(freq[i]);
            int res = 0;
            while (!pq.isEmpty()) {
                List<Integer> temp = new ArrayList<>();
                for (int i = 0; i <= k; i++) {
                    if (!pq.isEmpty()) {
                        if (pq.peek() > 1) {
                            temp.add(pq.peek() - 1);
                        }
                        pq.poll();
                    }
                    res += 1;
                    if (pq.isEmpty() && temp.size() == 0) break;
                }
                for (Integer i : temp) pq.add(i);
            }
            return res;
        }
    

      

  • 相关阅读:
    (译+原)std::shared_ptr及std::unique_ptr使用数组
    (转+原)ipp "No dlls were found in the Waterfall procedure"
    (原)vs2013编译boost1.60库
    (原+转)VS2013:正在从以下位置加载符号
    (原)直方图的相似性度量
    (原)Opencv中直方图均衡和图像动态范围拉伸的代码
    JAVA 8 新特性 Stream API 创建
    JAVA 8 新特性 Stream API 介绍
    JAVA 8 新特性 方法引用
    JAVA 8 新特性 函数式接口
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12457111.html
Copyright © 2011-2022 走看看