From bcdcdfb395453c6f8085fce02a709dcfe5c25348 Mon Sep 17 00:00:00 2001 From: gameloader Date: Tue, 19 Mar 2024 23:11:45 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 85 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 885c48b..32f0509 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -1531,3 +1531,88 @@ func findMinArrowShots(points [][]int) int { return res } ``` + +## day22 2024-03-19 + +### 621. Task Scheduler + +You are given an array of CPU tasks, each represented by letters A to Z, and a cooling time, n. Each cycle or interval allows the completion of one task. Tasks can be completed in any order, but there's a constraint: identical tasks must be separated by at least n intervals due to cooling time. + +Return the minimum number of intervals required to complete all tasks. + +![031901VKFQ0HNGWv](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/031901VKFQ0HNGWv.png) + +### 题解 + +拿到本题, 最直接的想法就是将每种任务的数量统计出来, 从大到小排序, 然后按照冷却时间轮流按序执行不同的任务, 不能执行任务的时间片留空. 某种任务全部执行完后, 该任务占据的时间片也留空. 知道全部任务都执行完需要的时间就是最少时间. 这是一种贪心的思想, 简单思考其正确性, 因为即使调换顺序, 在执行到某个时间时也不会比这种贪心算法执行的任务更多. + +### 代码 + +```go +func leastInterval(tasks []byte, n int) int { + tasknumber := map[byte]int{} + for _, task := range tasks{ + _, exist := tasknumber[task] + if !exist{ + tasknumber[task] = 1 + }else{ + tasknumber[task]++ + } + } + tasknumber_slice := []int{} + for _, value := range tasknumber{ + tasknumber_slice = append(tasknumber_slice, value) + } + sort.Ints(tasknumber_slice) + length := 0 + result := 0 + for { + length = len(tasknumber_slice) + for i:=1;i<=n+1;i++{ + if i<=length{ + if(tasknumber_slice[length-i] == 1){ + if i==1{ + tasknumber_slice = tasknumber_slice[:length-1] + }else{ + tasknumber_slice = append(tasknumber_slice[:length-i],tasknumber_slice[length-i+1:]...) + } + + }else{ + tasknumber_slice[length-i]-- + } + } + result++ + if len(tasknumber_slice)==0{ + goto Loop + } + } + sort.Ints(tasknumber_slice) + } + Loop: + return result +} +``` + +### 总结 + +看了0ms的解法, 十分惊艳, 与其将任务一个一个的安放到插槽中, 不如直接按照频率最大的任务算出必须存在的空插槽的个数, 再用剩余的任务去填这些空插槽, 最后只需要将任务总数和剩余的空插槽个数相加即可得到最终的时长. 到这里我想到, 其实频率最高的任务留出的空插槽数目是固定的, 只要将除频率最高之外的任务总数和空插槽数目相比, 若小于空插槽数目, 则最后时长就是频率最高任务完成需要的时长. 这里需要将和频率最高的任务频率相同的任务数目先减一计算算到任务总数中, 最后再加到最终的时间总数上. 若大于空插槽数目, 最终结果就是任务数目. + +```go +func leastInterval(tasks []byte, n int) int { + freq := make([]int, 26) + for _, task := range tasks { + freq[task-'A']++ + } + sort.Ints(freq) + + maxFreq := freq[25] + idleSlots := (maxFreq - 1) * n + + for i := 24; i >= 0 && freq[i] > 0; i-- { + idleSlots -= min(maxFreq-1, freq[i]) + } + idleSlots = max(0, idleSlots) + + return len(tasks) + idleSlots +} +```