题目描述
给定一个char数组,代表CPU需要做的任务,包含A-Z,不用考虑顺序,每个任务能在1个单位完成。但是有规定一个非负整数n代表两个相同任务之间需要至少n个时间单位。球最少数量的时间单位完成所有任务。
思路
先要找到最大的任务个数x,若总任务类数>=n,则时间至少为(x-1)*(n+1)+最大值类数;但是对于特殊情况:4A3B3C3D,n=2,则使用原来的思路(先放最多类的,再按照类别从前往后填空) 不能获得最小值。所以没有做出来。
Solution
总结了一下,LeetCode上的达人们的思路主要有这样几种:
- 先统计词频,再排序,从后往前找到第一个不是最大词频的下标i,结果是tasks.length或(c[25] - 1) * (n + 1) + 25 – i中大的那一个,25-i就是最大词频的任务类,这个和我的思路是一样的。证明:最大词频是k,则创建k个块,每一块开头是最大词频的任务构成的(输入AACCCDDEEE,则开头是CE),词频由大到小插入每一块。97.69%,10ms。
- 贪心,利用优先队列排序:队列中保存<类型,个数>的map,并且按照个数由大到小排序。按照词频由大到小取出n+1个或者队列中全部(若没有取出全部,则总长度要加上空闲个数),再把词频-1之后不为0的放回队列中。直到队列空了为止。——其实也和前面相同,总是选择词频最大的填入每一块。
- 使用操作系统的思想,在时间为time的时候,把time-1-n冻结的任务放回等待队列waitingQueue,在一个循环结束的时候,如果还有这一类task待完成,放到tasksTable。具体做法:先用HashMap统计词频,再用优先队列waitingQueue排序,声明一个冷却HashMap表coolDownTable,当队列不空或者冷却表不空的时候,找到冷却表time-n-1对应的任务char,拿出放到等待队列中,如果等待队列不空{拿出任务,剩余任务个数-1并放到tasksTable,如果剩余任务个数不为0放到coolDownTable.put(time, task); } time++。返回time
- 类似上面,模拟的思想:对于m个任务,先是每类任务的冷却时间-1,然后找到词频最大的任务及其下标,如果它的词频>-1,则取这个任务(词频-1,处理++,冷却时间+n);否则(所有任务词频都为-1),空闲+1.返回处理+空闲时间
代码
只是实现了第一个solution的代码:
public int leastInterval(char[] tasks, int n) {
int[] freq=new int[26];
int maxFreq=0,maxFreqCount=0;
for(int i=0;i<tasks.length;i++){
freq[tasks[i]-'A']++;
}
for(int i=0;i<26;i++){
if(freq[i]>maxFreq){
maxFreq=freq[i];
maxFreqCount=1;
}else if(freq[i]==maxFreq){
maxFreqCount++;
}
}
return Math.max(tasks.length,(maxFreq-1)*(n+1)+maxFreqCount);
}