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的特殊情况

  

 

posted @ 2018-12-05 20:14  流沙沙  阅读(809)  评论(0编辑  收藏  举报