Skip to content

Latest commit

 

History

History

621.Task-Scheduler

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

621.Task-Scheduler

解法1:模拟最优解的过程

此题非常类似 358.Rearrange-String-k-Distance-Apart。我们令n自加1,这样题意要求每n个相邻的位置不能有重复的元素.

设计一个大顶堆的priority_queue,PQ的元素是{freq,num}。每次取出权重最多的n种字符(除非PQ里面的元素个数少于n),将其freq减一后再放回队列中。

需要注意的是,即使队列中的元素少于n,只要没有完成所有的任务,根据题意的idle设定,计数器仍需要count+=n. 只有最后一轮(弹出后队列为空)时,计数器才 count+= num,其中num是队列弹出前的元素个数。

解法2:贪心构造

因为此题并不要求打印具体的实施方案,所以不需要像解法1那样完全地模拟这个流程。

我们找出频次最高的字符A,假设它的频次是MaxFreq。那么我们就将全部的元素分成MaxFreq组,每组的第一个就是A。同时我们给每组预留至少N个位置。这样,我们就合法地处理完了所有的A。如果有其他字符的频次也是MaxFreq,那么我们类似处理。示意图如下,总共有maxFreq行,每行靠前的位置都填充频次为MaxFreq的元素。除最后一行外,每行有N个位置。

A B 。。。。。
A B 。。。。。
A B 。。。。。
A B 。。。。。
A B 

接下来我们按照从上到下、从左到右的顺序,依次在待定的位置上填充第二高频的字符、第三高频的字符... 因为其他字符的频次都不会超过maxFreq-1,而我们有MaxFreq-1行,说明同一行里不会出现两个相同的字符。最终填充的结果会有两种可能:一种是上述的格子没有被填满:第二种是上述的格子已经填满了,但是我们还有字符没有填充。

对于第一种情况,如下图,我们将前MaxFreq-1行里没有被填充的位置都标记为idle,那么把这些行都拼接起来就是一个符合要求的方案。这个方案里,其实不管tasks具体的数目,总共的格子(也就是处理时间)是固定的,即(MaxFreq-1) * N + 零头,其中零头频次为MaxFreq的字符种数。

A B C D E H 。
A B C D F 。。
A B C D F 。。
A B C E G 。。
A B 

对于第二种情况,如下图,所有的idle位置都已经填满了,但是我们还有字符没填怎么办?这时候我们就可以打破每行只能填N个元素的限制,尽情地按照从上到下、从做到右的顺序继续填充在前MaxFreq-1行填充即可。这种方案的总格子数(即处理时间)其实就是tasks的大小。

A B C D E H L p t
A B C D F I M q u
A B C D F J N r
A B C E G K O s
A B 

显然,上述两种方案不可能共存。只要tasks的数目大于了规划的格子数(MaxFreq-1) * N + 零头,那么答案就是tasks.size();否则答案就是第一种方案。

Leetcode Link