给你一个用字符数组
tasks表示的 CPU 需要执行的任务列表,在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。然而,两个 相同种类 的任务之间必须有长度为整数n的冷却时间
这道题可能需要注意的地方:
-
- 根据冷却时间,有两种情况
- 任务类型大于等于n,只需要分配n个不同的任务就可以
- 任务类型小于n,分配完任务类型之后,需要用待机去填充冷却时间
-
- 为了保证尽可能多的执行任务,每次都先取剩余次数最多的任务执行
下面是解题思路:
以 tasks = ["A","A","A","B","B","B"] n = 2 为例
-
- 统计每个任务出现的次数,
["A","A","A","B","B","B"]的统计结果为{"A": 3, "B": 3},映射成剩余任务次数数组rest[3, 3]
- 统计每个任务出现的次数,
-
- 建立有效数组
nextValid,来统计当前任务是否可以调度。
这里是否可以调度的含义,还是以实例说明:这里的冷却时间为
2,如果先执行A,那么下一个可以是B,接下里就只能待命,如下图时刻: 1 2 3 4 5 6 7 ... 队列: A B 待命 A B 待命 A ...最开始可以执行
A或者B,先将nextValid赋值为[1, 1],这里nextValid的index与剩余次数统计数组rest的index相对应 - 建立有效数组
-
-
开始执行任务,当前时刻为
1,只要nextValid小于等于这个值,即可以执行对应任务
- a. 首先查找有效值最小(表明最久没执行)且剩余次数不为
0的任务,例子中开始这里都是1,两个都符合,时刻1有可以执行的任务 - b. 然后用
1去查找属于次数最多的任务,这里都是3次,取任务A执行 - c. 修改任务剩余次数:
[2, 3],同时修改A的nextValid的值(当前时刻 + 冷却时间 + 1):[4, 1] - d. 执行下一个任务,时刻为
2, - e. 在
nextValid中寻找等于小于2的值,得到1,说明时刻2有可以执行的任务 - f. 然后查找
nextValid小于时刻2,且次数最多的任务的index,结果为1,执行任务B - g. 然后修改任务
B次数,rest为[2, 2],修改B的nextValid的值(当前时刻 + 冷却时间 + 1):[4, 2 + 2 + 1] - h. 下一个时刻为
3,查找在nextValid查找最小值,4,所以时刻3没有任务可以执行,待命状态,同时将时刻改成4 - i. 在
nextValid中查找小于等于4且数量最大的任务的索引0,执行0对应的任务A - j. 修改任务次数
[1, 2],以及nextValid的值:[4 + 2 +1, 5] - ...重复上述步骤
-
-
- 返回最后的执行任务的时刻
function leastInterval(tasks: string[], n: number): number {
if (n === 0) return tasks.length
const obj = {}
// 统计任务数量
for(let i = 0; i < tasks.length; i++) {
obj[tasks[i]] = (obj[tasks[i]] || 0) + 1
}
const taskKindLength = Object.keys(obj).length
const nextValid = new Array(taskKindLength).fill(1)
// 剩余数量数组
const rest: number[] = Object.values(obj)
// 执行任务的时刻
let times = 0
for(let i = 0; i < tasks.length; i++) {
times++
// 找 距离可用的任务
let minNextValid = Number.MAX_VALUE
for(let i = 0; i < taskKindLength; i++) {
// 保证还有 该任务
if (rest[i] > 0) {
minNextValid = Math.min(minNextValid, nextValid[i])
}
}
times = Math.max(times, minNextValid)
let best = -1
for(let j = 0; j < taskKindLength; j++) {
// 保证任务是符合冷却时间的
if (rest[j] && nextValid[j] <= times) {
// 找次数最多的任务
if (best === -1 || rest[j] > rest[best]) {
best = j
}
}
}
nextValid[best] = times + n + 1
rest[best]--
}
return times
}