621. Task Scheduler

Description

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].

Solution

Greedy

這道題顯然需要用Greedy去做,優先做出現頻率高的task。原本想構造一個Tuple class存儲某類task下一個預期的執行時間,但是發現有問題,考慮這個例子:
[a,a,a,b,c,d], n = 2
隊列里面一開始存儲的是(a, 3, 1), (b, 1, 1), (c, 1, 1), (d, 1, 1)
那么首先做完一個task a之后,(a, 2, 4)重新入隊列,接下來會做task b和task c,然后這種算法下面會做task d,而不是task a!所以這樣做不行。

后來發現并不需要estimate time,將時間分段來看,每段長度為n + 1,然后往每個時間片上添任務就行了。這樣一定可以保證每個時間片內相同的任務之間的距離至少是n。

class Solution {
    public int leastInterval(char[] tasks, int n) {
        Map<Character, Integer> freq = new HashMap<>();
        for (char task : tasks) {
            freq.put(task, freq.getOrDefault(task, 0) + 1);
        }
        
        PriorityQueue<Map.Entry<Character, Integer>> queue 
            = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
        queue.addAll(freq.entrySet());
        
        int time = 0;
        while (!queue.isEmpty()) {
            int k = n + 1;
            List<Map.Entry<Character, Integer>> tmpList = new LinkedList<>();
            
            while (k > 0 && !queue.isEmpty()) {
                Map.Entry<Character, Integer> entry = queue.poll();
                ++time;     // one task executed
                --k;
                entry.setValue(entry.getValue() - 1);
                if (entry.getValue() > 0) {
                    tmpList.add(entry);
                }
            }
            
            queue.addAll(tmpList);  // add tasks back to queue
            if (!queue.isEmpty()) {
                time += k;  // idle time
            }
        }
        
        return time;
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容