621. 任务调度器 中等
给你一个用字符数组 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]
代码参考:
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
fmt.Println(leastInterval([]byte{'A', 'A', 'A', 'B', 'B'}, 2))
}
// 思路:从高频字母开始
// A _ _ A _ _ A _ _
// A B _ A B _ A _ _
// A B _ A B _ A // bingo
func leastInterval(tasks []byte, n int) int {
m := make(map[byte]int)
for _, t := range tasks {
m[t]++
}
counts := make(map[int][]byte)
for b, count := range m {
counts[count] = append(counts[count], b) // 统计各字母的出现频率
}
var freqs []int
for c := range counts {
freqs = append(freqs, c)
}
sort.Ints(freqs)
maxFreq := freqs[len(freqs)-1]
c := maxFreq * (n + 1)
holders := make([]byte, c) // 占位 // 注意遍历顺序是不定的
for i := range holders {
if i%(n+1) == 0 {
holders[i] = counts[maxFreq][0] // 初始化占位数组
}
}
counts[maxFreq] = counts[maxFreq][1:]
// 从后向前遍历字符,填充
var cs []int
for count := range counts {
cs = append(cs, count)
}
sort.Ints(cs)
// debug(holders)
for i := len(cs) - 1; i >= 0; i-- {
c = cs[i]
bs := counts[c]
for _, b := range bs {
for start, h := range holders {
if h == 0 { // 向后占位
for i := start; c >= 0 && i < len(holders); c-- {
holders[i] = b
i += n + 1
}
break
}
}
}
}
holders = trimRight(holders)
debug(holders) // A B 0 A B 0 A B
return len(holders) // 8
}
func trimRight(bs []byte) []byte {
for i := len(bs) - 1; i >= 0; i-- {
if bs[i] == byte(0) {
bs = bs[:i]
} else {
break
}
}
return bs
}
func debug(bs []byte) {
s := string(bs)
s = strings.Replace(s, "\x00", "0", -1)
fmt.Println(strings.Join(strings.Split(s, ""), " "))
}
最后编辑: kuteng 文档更新时间: 2021-06-05 10:16 作者:kuteng