1. 程式人生 > >621. Task Scheduler(任務行程表)

621. Task Scheduler(任務行程表)

Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks.Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.

However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle.

You need to return the least number of intervals the CPU will take to finish all the given tasks.

Example 1:

Input: tasks = [‘A’,’A’,’A’,’B’,’B’,’B’], n = 2
Output: 8
Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.

Note:

The number of tasks is in the range [1, 10000].
The integer n is in the range [0, 100].

這道題讓我們安排CPU的任務,規定在兩個相同任務之間至少隔n個時間點。說實話,剛開始博主並沒有完全理解題目的意思,後來看了大神們的解法才悟出個道理來。下面這種解法參考了大神fatalme的帖子,由於題目中規定了兩個相同任務之間至少隔n個時間點,那麼我們首先應該處理的出現次數最多的那個任務,先確定好這些高頻任務,然後再來安排那些低頻任務。如果任務F的出現頻率最高,為k次,那麼我們用n個空位將每兩個F分隔開,然後我們按順序加入其他低頻的任務,來看一個例子:

AAAABBBEEFFGG 3

我們發現任務A出現了4次,頻率最高,於是我們在每個A中間加入三個空位,如下:

A—A—A—A

AB–AB–AB–A (加入B)

ABE-ABE-AB–A (加入E)

ABEFABE-ABF-A (加入F,每次儘可能填滿或者是均勻填充)

ABEFABEGABFGA (加入G)

再來看一個例子:

ACCCEEE 2

我們發現任務C和E都出現了三次,那麼我們就將CE看作一個整體,在中間加入一個位置即可:

CE-CE-CE

CEACE-CE (加入A)

注意最後面那個idle不能省略,不然就不滿足相同兩個任務之間要隔2個時間點了。

這道題好在沒有讓我們輸出任務安排結果,而只是問所需的時間總長,那麼我們就想個方法來快速計算出所需時間總長即可。我們仔細觀察上面兩個例子可以發現,都分成了(mx - 1)塊,再加上最後面的字母,其中mx為最大出現次數。比如例子1中,A出現了4次,所以有A—模組出現了3次,再加上最後的A,每個模組的長度為4。例子2中,CE-出現了2次,再加上最後的CE,每個模組長度為3。我們可以發現,模組的次數為任務最大次數減1,模組出現次數為n+1,最後加上的字母個數為出現次數最多的任務,可能有多個並列。這樣三個部分都搞清楚了,寫起來就不難了,我們統計每個大寫字母出現的次數,然後排序,這樣出現次數最多的字母就到了末尾,然後我們向前遍歷,找出出現次數一樣多的任務個數,就可以迅速求出總時間長了,參見程式碼如下:

解法一:

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        vector<int> cnt(26, 0);
        for (char task : tasks) {
            ++cnt[task - 'A'];
        }
        sort(cnt.begin(), cnt.end());
        int i = 25, mx = cnt[25], len = tasks.size();
        while (i >= 0 && cnt[i] == mx) --i;
        return max(len, (mx - 1) * (n + 1) + 25 - i);
    }
};