621. Task Scheduler

Posted andywu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了621. Task Scheduler相关的知识,希望对你有一定的参考价值。

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.

题目含义:给定一个char数组,代表CPU需要做的任务,包含A-Z,不用考虑顺序,每个任务能在1个单位完成。但是有规定一个非负整数n代表两个相同任务之间需要至少n个时间单位。求最少数量的时间单位完成所有任务。

 

解法一:贪心,利用优先队列排序:队列中保存<类型,个数>的map,并且按照个数由大到小排序。按照词频由大到小取出n+1个或者队列中全部(若没有取出全部,则总长度要加上空闲个数),再把词频-1之后不为0的放回队列中。直到队列空了为止。——其实也和前面相同,总是选择词频最大的填入每一块。

 1     public int leastInterval(char[] tasks, int n) {
 2         Map<Character, Integer> taskArray = new HashMap<>();
 3         for (int i = 0; i < tasks.length; i++) {
 4             taskArray.put(tasks[i], taskArray.getOrDefault(tasks[i], 0) + 1);
 5         }
 6 
 7         PriorityQueue<Map.Entry<Character, Integer>> p = new PriorityQueue<>(
 8                 (a, b) -> a.getValue() != b.getValue() ? b.getValue() - a.getValue() : a.getKey() - b.getKey()); //按照单词次数由高到低排列
 9         p.addAll(taskArray.entrySet());
10         int count = 0; //总共要运行的次数
11         while (!p.isEmpty()) {
12             int k = n + 1; //同名任务间隔长度是n
13             List<Map.Entry<Character, Integer>> tempTask = new ArrayList<>();  //这一波被取出来执行的任务集合
14             while (k > 0 && !p.isEmpty()) {
15                 Map.Entry<Character, Integer> t = p.poll();
16                 t.setValue(t.getValue() - 1);//execute ont task
17                 tempTask.add(t);
18                 k--;
19                 count++;
20             }
21 
22             for (Map.Entry<Character, Integer> e : tempTask) { //如果还有剩余任务,再次放回到队列中
23                 if (e.getValue() > 0) p.add(e); // add valid tasks
24             }
25 
26             if (p.isEmpty()) {
27                 break;
28             }
29 
30             if (k > 0) count += k; //if k > 0, then it means we need to be idle   //只执行任务填不满任务间隔k,需要放空
31         }
32         return count;        
33     }

方法二:按照出现频率最多(假设频率为k)的将其分为了k块,然后每一轮向这k个区间个插入1个。

按照任务从多到少依次为每个块分配任务。我们这里假定,A一定能够符合距离下一个A的冷却时间为n,那么跟在A后面的也一定符合。只要保证A符合就行了,其他任务的的符合要求都可以由A的符合推导出来。

例如:AAAABBBEEFFGG 3

Frame: "AXXXAXXXAXXXA"
insert ‘B‘: "ABXXABXXABXXA" <--- ‘B‘ has higher frequency than the other characters, insert it first.
insert ‘E‘: "ABEXABEXABXXA"
insert ‘F‘: "ABEFABEXABFXA" <--- each time try to fill the k-1 gaps as full or evenly as possible.
insert ‘G‘: "ABEFABEGABFGA"

c[25]是出现最多的字母数,所以(c[25] - 1)是分块数,例如A(4)次数最多,间隔n(3)(A***A***A***A)则重复的段落数为4-1=3。间隔是n,包含领头的A在内,每个间隔的长度是n+1=3+1=4.
所以整个段落长度是(c[25] - 1) * (n + 1)。因为出现频率最高的元素可能不止一个,我们假设为k个,那么这种情况下最终的时间需求为:(c[25]-1)*(n+1)+k
 
1         int[] c = new int[26];
2         for(char t : tasks){
3             c[t - ‘A‘]++;
4         }
5         Arrays.sort(c);
6         int i = 25;
7         while(i >= 0 && c[i] == c[25]) i--;
8 
9         return Math.max(tasks.length, (c[25] - 1) * (n + 1) + 25 - i);

 

以上是关于621. Task Scheduler的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode 621] Task Scheduler

[LeetCode 621] Task Scheduler

621. Task Scheduler

621. Task Scheduler

621. Task Scheduler

621. Task Scheduler