题目描述
给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。
然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的 最短时间 。
示例 1:
输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。
示例 2:
输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 0
输出:6
解释:在这种情况下,任何大小为 6 的排列都可以满足要求,因为 n = 0
[“A”,“A”,“A”,“B”,“B”,“B”]
[“A”,“B”,“A”,“B”,“A”,“B”]
[“B”,“B”,“B”,“A”,“A”,“A”]
…
诸如此类
示例 3:
输入:tasks = [“A”,“A”,“A”,“A”,“A”,“A”,“B”,“C”,“D”,“E”,“F”,“G”], n = 2
输出:16
解释:一种可能的解决方案是:
A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> (待命) -> (待命) -> A -> (待命) -> (待命) -> A
提示:
1 <= task.length <= 104
tasks[i] 是大写英文字母
n 的取值范围为 [0, 100]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/task-scheduler
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
看到这几个示例,最先想到的就是数学中求组合数的插入法
要满足所有相同字符都间隔 n 位,那么只需要排列最多的字符就好了
拿示例三举例:tasks = [“A”,“A”,“A”,“A”,“A”,“A”,“B”,“C”,“D”,“E”,“F”,“G”], n = 2
先排列 字符个数最多的 “A”
A -> () -> () -> A -> () -> () -> A -> () -> () -> A -> () -> () -> A -> () -> () -> A
然后在 A 的后边插入第二长的字符 B (其实剩下一样长了,顺序取而已)
A -> B -> () -> A -> () -> () -> A -> () -> () -> A -> () -> () -> A -> () -> () -> A
以此类推,其他字符会填满这些空档。
结束了?没,假如其他的字符总个数超过了这些空档的个数,怎么办?
可以在拓展一下,如果继续按这种方式,往后边拓展 A 呢?
举例 :tasks = [“A”,“A”,“A”,“B”,“B”,“C”,“C”,“D”,“E”,“F”,“G”], n = 2
A -> () -> () -> A -> () -> () -> A
A -> B -> () -> A -> () -> () -> A -> () -> () -> B
A -> B -> () -> A -> C -> () -> A -> C -> () -> B
A -> B -> D -> A -> C -> () -> A -> C -> () -> B
A -> B -> D -> A -> C -> E -> A -> C -> F -> B -> G
这样顺序下来就好了,不用担心添加的 B 和插入的 B 会间隔不够,因为 A 是个数最多的,B 再多也只能和 A 一样长,也就是说 B 填充下来,永远不会到 最后一个 A 后边。
这种情况,需要的时间就是和长度一样长。
还有一种情况需要注意,那就是出现几个等长,怎么办?
其实很简单,A B C 个数相同且最大,那么只需要在A后边再加上B C就好了。
反思错误
无
Java代码
class Solution {
public int leastInterval(char[] tasks, int n) {
// 字符数组 总长度
int len = tasks.length;
// 如果间隔是0,那么直接返回总长度
if(n == 0) return len;
// 映射字符个数
int[] taskc = new int[26];
// 最大个数
int max = 0;
// cnt 最大个数的字符有几种;idx 计算字符对应的脚标
int cnt = 0, idx = 0;
for(int i=0;i<len;++i) {
// 每次都计算tasks[i]-'A',感觉浪费时间,所以加了一个idx
idx = tasks[i]-'A';
taskc[idx]++;
max = max > taskc[idx] ? max : taskc[idx];
}
for(int count:taskc) {
cnt += count==max ? 1 : 0;
}
int maxlen = (max-1) * (n+1) + cnt;
return maxlen > len ? maxlen : len;
}
}
执行结果
执行用时:2 ms , 在所有 Java 提交中击败了 94.43% 的用户
内存消耗: 40 MB , 在所有 Java 提交中击败了 9.60% 的用户
通过测试用例:71 / 71