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;
        }
    

      

  • 相关阅读:
    (原)x264代码中的码流控制学习
    (原)关于OpenSL ES播放音频数据的一个奇怪的问题
    (原)理解码率控制模式(x264,x265,vpx)
    CentOS清除用户登录记录和命令历史方法
    2B销售提升业绩的5项技能
    Cookie中的httponly的属性和作用
    如何开展HW行动
    护网结束,复盘攻防,聊聊安全! 2019
    2018-11-21(34)《阿里铁军》阅后记!
    你了解渗透测试与红蓝队对抗的区别吗?
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12457111.html
Copyright © 2011-2022 走看看