题目描述
给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。
然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的最短时间。
示例 :
输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。
提示:
任务的总个数为 [1, 10000]。
n 的取值范围为 [0, 100]。
题解:桶排序
思路:
因为相同任务必须要有时间片为 n 的间隔,所以我们先把出现次数最多的任务 A 安排上(当然你也可以选择任务 B)。例子中 n = 2,那么任意两个任务 A 之间都必须间隔 2 个单位的时间:
A -> (单位时间) -> (单位时间) -> A -> (单位时间) -> (单位时间) -> A
中间间隔的单位时间可以用来安排别的任务,也可以处于“待命”状态。当然,为了使总任务时间最短,我们要尽可能地把单位时间分配给其他任务。现在把任务 B 安排上:
A -> B -> (单位时间) -> A -> B -> (单位时间) -> A -> B
最后一个 A 之后是否还有任务跟随取决于是否存在与任务 A 出现次数相同的任务。
特殊情况
然而存在一种特殊情况,例如:
输入: tasks = [“A”,“A”,“A”,“B”,“B”,“B”,“C”,“C”,“D”,“D”], n = 2
输出: 10
执行顺序: A -> B -> C -> A -> B -> D -> A -> B -> C -> D
此时如果按照上述方法计算将得到结果为 8,比数组总长度 10 要小,应返回数组长度。
代码:
- 将任务按类型分组,正好A-Z用一个int[26]保存任务类型个数
- 对数组进行排序,优先排列个数(count)最大的任务,如题得到的时间至少为 retCount =(count-1)* (n+1) + 1 ==> A->X->X->A->X->X->A(X为其他任务或者待命)
- 再排序下一个任务,如果下一个任务B个数和最大任务数一致,
则retCount++ ==> A->B->X->A->B->X->A->B - 如果空位都插满之后还有任务,那就随便在这些间隔里面插入就可以,因为间隔长度肯定会大于n,在这种情况下就是任务的总数是最小所需时间
class Solution {
public int leastInterval(char[] tasks, int n) {
int len = tasks.length;
int[] arr = new int[26];
//计数
for(int i=0;i<len;i++){
arr[tasks[i]-'A']++;
}
//找出最大值
Arrays.sort(arr);
int max = arr[25];
//计算任务书
int ret_time=(max-1)*(n+1)+1;
int i=24;
//若最大数目相同,则最在最后添加任务。
while(i>=0&&arr[i]==max){
ret_time++;
i--;
}
//如果空位插满还有空间,则任务数就是最小时间
return Math.max(ret_time,len);
}
}