621. Task Scheduler

本文介绍了如何通过两种不同的算法来解决CPU任务调度问题,确保在有限的冷却时间内完成所有任务。一种是使用优先队列进行贪心算法实现,另一种则是通过分析任务频率分布来优化调度策略。

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

 

转载于:https://www.cnblogs.com/wzj4858/p/7678582.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值