排序
由於相同的任務之間必須有 n 的冷卻時間,所以我們可以想到按照任務的數量來安排它們,即一種任務的出現次數越多,我們就越早地安排。例如有 5 種任務 A, B, C, D, E,且它們分別有 6, 1, 1, 1, 1 個時,假設冷卻時間 n = 2,那麼我們首先安排任務 A,隨後在 2 單位的冷卻時間裏,我們安排任務 B, C,隨後繼續安排任務 A,再安排任務 D, E,以此類推。
因此我們得到了一種安排的方法:我們規定 n + 1 個任務爲一輪,這樣的好處是同一輪中一個任務最多隻能被安排一次。在每一輪中,我們將當前的任務按照它們剩餘的次數降序排序,並選擇剩餘次數最多的 n + 1 個任務依次執行。如果任務的種類 t 少於 n + 1 個,就只選擇全部的 t 種任務,其餘的時間空閒。這樣做的正確性在於,由於冷卻時間的存在,出現次數較多的那些任務如果不盡早安排,將會導致大量空閒時間的出現,因此貪心地將出現次數較多的任務安排在前面是合理的。同時我們可以保證,這一輪的第 k 個任務距離上一次執行至少有 n 個單位的冷卻時間。我們可以使用逆向思維來證明:假設第 r 輪中某個任務在第 k 個執行,那麼說明它在第 r 輪時爲數量第 k 多的任務。在第 r 輪結束後,第 1 多到第 k 多的任務的數量都會減少 1,因此在第 r + 1 輪,這個任務最多也只能是數量第 k 多,因此它如果被執行,一定滿足冷卻時間的要求。
class Solution {
public int leastInterval(char[] tasks, int n) {
int[] map = new int[26];
for(char task :tasks){
map[task - 'A']++;
}
Arrays.sort(map);
int count = 0;
while(map[25] >0){
int i = 0 ;
while(i<=n){
if(map[25] == 0){
break;
}
if(i<26 &&map[25-i] >0){
map[25-i]--;
}
count++;
i++;
}
Arrays.sort(map);
}
return count;
}
}