力扣621——任務調度器

這道題主要是找規律,優化的時候能夠採用貪心算法的思想。
<!-- more -->java

原題

給定一個用字符數組表示的 CPU 須要執行的任務列表。其中包含使用大寫的 A - Z 字母表示的26 種不一樣種類的任務。任務能夠以任意順序執行,而且每一個任務均可以在 1 個單位時間內執行完。CPU 在任何一個單位時間內均可以執行一個任務,或者在待命狀態。git

然而,兩個相同種類的任務之間必須有長度爲 n 的冷卻時間,所以至少有連續 n 個單位時間內 CPU 在執行不一樣的任務,或者在待命狀態。github

你須要計算完成全部任務所須要的最短期算法

示例 1:segmentfault

輸入: tasks = ["A","A","A","B","B","B"], n = 2
輸出: 8
執行順序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B.

注:數組

  1. 任務的總個數爲 [1, 10000]。
  2. n 的取值範圍爲 [0, 100]。

原題url:https://leetcode-cn.com/probl...優化

解題

找規律

這道題的思路,正向推導的話,其實就是優先排出現次數多的任務,根據間隔 n ,填充任務,直到全部任務的次數最終都減爲0。url

所以,咱們能夠用數組存儲任務的總次數(由於用大寫英文字母表示任務,那就表明最多隻能有26種任務),排序以後,按照間隔 n ,從大到小取任務,取完後,再對數組排序,重複上述取任務的過程,直到數組的最大值爲0。spa

接下來咱們看看代碼:code

public class Solution {
    public int leastInterval(char[] tasks, int n) {
        // 將task放入數組中
        int[] countArray = new int[26];
        for (char task: tasks) {
            countArray[task - 'A']++;
        }
        // 從小到大,進行排序
        Arrays.sort(countArray);
        // 最終耗時
        int time = 0;
        // 從大到小開始遍歷
        while (countArray[25] > 0) {
            // 每次遍歷前n個數
            int i = 0;
            while (i <= n) {
                // 說明全部任務已經執行完成
                if (countArray[25] == 0) {
                    break;
                }
                // 遍歷
                if (i < 26 && countArray[25 - i] > 0) {
                    countArray[25 - i]--;
                }
                // 耗時+1
                time++;
                // 更換任務
                i++;
            }
            // 從小到大排序
            Arrays.sort(countArray);
        }
        return time;
    }
}

提交OK,但執行時間上確實不太好,只戰勝了47.62%的 java 執行時間,其時間複雜度爲O(time), time 表明最終的執行時間。

貪心算法

咱們再來想一想這道題,影響最終執行時間的,有兩個因素,一個是任務中出現的最大次數,另外一個就是間隔 n 了。

若是咱們站在最多任務的角度,來看這個問題,假設其最大次數爲 maxCount,那麼該任務所需的最短執行時間爲(maxCount - 1) * (n + 1) + 1,若是還有其餘 i 個和 maxCount 相同次數的任務,那麼須要在最終的結果上再加上 i。

那麼上面求出來的就是正確答案了嗎?

並非,由於上面的最短期,是當剩餘時間片可以塞滿任務數小於 maxCount 的全部任務。假設 n 很小,那麼剩餘任務確定須要在任務數等於 maxCount 的那些任務執行完以後,還要繼續執行。

但由於最大任務已經能夠知足在間隔時間內執行完,那麼出現次數小於 maxCount 的任務,確定能夠連續執行完成的,也就是不須要空閒等待時間。那麼此時的最短執行時間也就是總任務數了。

接下來咱們看看代碼:

public class Solution {
    public int leastInterval(char[] tasks, int n) {
        if (tasks.length == 0 || n == 0) {
            return tasks.length;
        }

        // 將task放入數組中
        int[] countArray = new int[26];
        for (char task : tasks) {
            countArray[task - 'A']++;
        }
        // 從小到大,進行排序
        Arrays.sort(countArray);
        // 獲取最大次數
        int maxCount = countArray[25];
        // 若是其餘次數都比maxCount小的話,求出針對maxCount的最短期
        int result = (maxCount - 1) * (n + 1);
        // 遍歷countArray
        for (int i = 25; i >= 0; i--) {
            // 若是有和maxCount相同的,則執行時間+1
            if (countArray[i] == maxCount) {
                result++;
            }
            // 不然,直接結束
            else {
                break;
            }
        }
        
        // 若是總任務數比理論上的最短期長,說明任務不少,但能夠把每一個桶填滿,所以最短期也就是總任務數
        return Math.max(result, tasks.length);
    }
}

提交OK ,在全部 Java 提交中擊敗了100.00%的用戶,確實快了不少。其時間複雜度爲O(M),M 表明總任務數。

總結

以上就是這道題目個人解答過程了,不知道你們是否理解了。這道題主要是找規律,優化的時候能夠採用貪心算法的思想。

有興趣的話能夠訪問個人博客或者關注個人公衆號、頭條號,說不定會有意外的驚喜。

https://death00.github.io/

公衆號:健程之道

相關文章
相關標籤/搜索