码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode621 - Task Scheduler - medium

时间:2018-09-16 12:30:50      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:i++   default   sam   origin   时间   就是   取出   bre   queue   


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

 

leetcode621 - Task Scheduler - medium

标签:i++   default   sam   origin   时间   就是   取出   bre   queue   

原文地址:https://www.cnblogs.com/jasminemzy/p/9654954.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!