leetcode 621 任务调度器
题目描述:CPU执行任务,每个任务需要1个单位的执行时间,两个相同任务之间需要有n个时间间隔的冷却时间,求CPU执行这些任务最少需要多少时间。
例子:
输入:AAABBBCCCCC, n=2(其中A,B,C表示三种不同的任务)
输出:13
解释:CPU执行可以为CABCABCABC_ _ C (_表示CPU待命状态)
两种解法。
第一种解法:用优先队列,在n个时间内,按照任务出现次数优先输出执行次数多的任务。
第二种解法:经过一定的数学分析,发现CPU执行任务的时间只取决于出现次数最多的任务次数。
两种解法的比较:
优先队列方法比较直观,运行效率略低。
数学分析法需要前期作一定的数学分析。运行效率高,但分析过程有时难以想到,并且需要考虑特殊情况(n=0)
1. 优先队列
def leastInterval(self, tasks, n): """
优先队列 :type tasks: List[str] :type n: int :rtype: int """ n+=1 ans=0 d=collections.Counter(tasks) heap=[-c for c in d.values()] heapq.heapify(heap) while heap: stack=[] cnt=0 for _ in range(n): if heap: c=heapq.heappop(heap) cnt+=1 if c<-1: stack.append(c+1) for item in stack: heapq.heappush(heap,item) ans+=heap and n or cnt # if heap: n else: cnt return ans
2. 数学分析
可以简化为,挑出出现次数最多的任务F,假设其出现次数为M次,那么最终的结果就是在M个任务F之间插入n个时间段。
因此对于前n-1个F,一定有(M-1)*(n+1)个执行次数。
对于最后1个F,可能存在的情况是多个任务都出现了F次,
比如 CCCAAABBB, n=2
假设选定出现次数最多的任务F为C,那么前2个周期为C_ _ C _ _
后面的一个周期为CAB,即再加上出现次数为最大频次的任务个数。
还有一种特殊情况:每个任务都出现了1次。那么此时执行任务的最少次数就是任务列表的长度。
def leastInterval(self, tasks, n): """ :type tasks: List[str] :type n: int :rtype: int """ d=collections.Counter(tasks) v=d.values() M = max(d.values()) ans = (M-1)*(n+1) for i in v: if i==M: ans+=1 return max(ans,len(tasks)) #解决n=0的特殊情况