zoukankan      html  css  js  c++  java
  • leetcode621


    Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks.Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.
    However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.
    You need to return the least number of intervals the CPU will take to finish all the given tasks.
    Example 1:
    Input: tasks = ["A","A","A","B","B","B"], n = 2
    Output: 8
    Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.
    Note:
    1. The number of tasks is in the range [1, 10000].
    2. The integer n is in the range [0, 100].

    1.max堆。
    1.建造一个堆,它按照字符出现的频率从大到小吐出频率。
    2.统计字符频率。
    3.在堆非空时都进行while循环,内部做一个n+1长度的循环cycle,当然也可能走不完这个cycle。这个cycle的目的是从堆取,把前n+1个最棘手(频率最高最需要早点安排)的任务排在这个cycle里。每次取出来后还要把减掉的频率记一下在temp里,最后一起放回去。如果heap里没数取了说明这一轮cycle放不满,你接下来要空循环来加idle凑time。如果heap里没数取了而且temp里也没数取了,说明下一轮肯定没了,这是最后一轮,从而不用接着空循环加idle凑满n+1,赶紧break走人吧。

    2.数学法。
    其实cycle数是由最大频率决定的。总time基本上= (maxF - 1)* (n + 1) + (f为最大频率的字符有多少种)。如果出现这个time算出来比总task数还少的情况,那就取task,也就是两者取其大。但我总觉得这个很难和面试官好好证明这个为什么是正确的。

    细节:
    1.用temp数组在最后放回去更新的频率是避免在一个cycle里放重复的任务。因为你刚更新了频率就放回去可能还是最大频率,接着马上又被拿出来了。
    2.先插最大的比如A,然后插第二大的比如B,这样下去不用担心比如B会不会在n时间内撞到。因为最大的是频率最大,那么就是有A活的一天才有B,那永远都有A帮你维持n的距离,不用担心。
    3.maxHeap比较器的优雅写法(对基础类型):new PriorityQueue<>(Collections.reverseOrder());
    4.比较器内部compare(T a, T b)内部的T的填写严格按照泛型指定的类型,比如对Integer的比较器,你这里就写Integer不能写int。这是Override啊同学。

    实现:

    class Solution {
        public int leastInterval(char[] tasks, int n) {
            
            // PriorityQueue<Integer> maxHeap = new PriorityQueue<>(new Comparator<Integer>() {
            //     @Override
            //     // P2: int a, int b是错的,严格按照泛型来。
            //     public int compare(Integer a, Integer b) {
            //         return b - a;
            //     }
            // });
            // P1: 自带数据结构的大跟堆的优雅写法
            PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
            
            Map<Character, Integer> map = new HashMap<>();
            for (char c : tasks) {
                map.put(c, map.getOrDefault(c, 0) + 1);
            }
            for (char c : map.keySet()) {
                maxHeap.offer(map.get(c));
            }
            
            int time = 0;
            while (!maxHeap.isEmpty()) {
                List<Integer> temp = new ArrayList<>();
                for (int i = 0; i < n + 1; i++) {
                    if (!maxHeap.isEmpty()) {
                        if (maxHeap.peek() > 1) {
                            temp.add(maxHeap.peek() - 1);
                        }
                        maxHeap.poll();
                    }
                    time++;
                    if (maxHeap.isEmpty() && temp.isEmpty()) {
                        break;
                    }
                }
                for (int newF : temp) {
                    maxHeap.offer(newF);
                }
            }
            return time;
        }
    }
  • 相关阅读:
    预搜索,不匹配;反向预搜索,不匹配
    反向引用 /1, /2...
    贪婪与非贪婪模式
    其他一些代表抽象意义的特殊符号
    修饰匹配次数的特殊符号
    自定义能够匹配 ' 多种字符' 的表达式
    能够与 ' 多种字符' 匹配的表达式
    6)添加带有颜色的那个画板
    5)添加快捷键
    4)记住我的图形
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9654954.html
Copyright © 2011-2022 走看看