1. 程式人生 > >leetcode 621 任務排程器

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