【LeetCode】每日一題621. 任務排程器
621. 任務排程器
給你一個用字元陣列 tasks 表示的 CPU 需要執行的任務列表。其中每個字母表示一種不同種類的任務。任務可以以任意順序執行,並且每個任務都可以在 1 個單位時間內執行完。在任何一個單位時間,CPU 可以完成一個任務,或者處於待命狀態。
然而,兩個 相同種類 的任務之間必須有長度為整數 n 的冷卻時間,因此至少有連續 n 個單位時間內 CPU 在執行不同的任務,或者在待命狀態。
你需要計算完成所有任務所需要的 最短時間 。
示例 1:
輸入:tasks = ["A","A","A","B","B","B"], n = 2
輸出:8
解釋:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
在本示例中,兩個相同型別任務之間必須間隔長度為 n = 2 的冷卻時間,而執行一個任務只需要一個單位時間,所以中間出現了(待命)狀態。
示例 2:
輸入:tasks = ["A","A","A","B","B","B"], n = 0
輸出:6
解釋:在這種情況下,任何大小為 6 的排列都可以滿足要求,因為 n = 0
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
...
諸如此類
示例 3:
輸入:tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
輸出:16
解釋:一種可能的解決方案是:
A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> (待命) -> (待命) -> A -> (待命) -> (待命) -> A
提示:
- 1 <= task.length <= 104
- tasks[i] 是大寫英文字母
- n 的取值範圍為 [0, 100]
方法一:優先佇列
因為要最短時間,在間隔允許的情況下,應該選擇任務次數剩餘最多的執行,所以採用優先佇列把任務次數多的放前面。
- 先統計每個任務的次數,再根據出現次數從大到小構建優先佇列
- 因為每個任務需要間隔 n ,所以每輪需要從佇列中彈出 n + 1 個任務執行,不夠 n + 1 剩餘的執行「待命」
- 彈出來的任務執行後還有次數,放入臨時表 temp 中,在一輪結束後放回佇列
public int leastInterval(char[] tasks, int n) {
// 統計每個任務的次數
int[] counts = new int[26];
for (Character c : tasks) {
counts[c - 'A']++;
}
// 根據任務次數從大到小構建優先佇列
PriorityQueue<Character> queue = new PriorityQueue<>(Comparator.comparingInt(c -> -counts[c - 'A']));
for (int i = 0; i < 26; i++) {
if (counts[i] > 0) {
queue.offer((char) (i + 'A'));
}
}
int time = 0;
List<Character> temp;// 臨時儲存每輪從佇列中取出來的任務
while (queue.size() > 0) {
temp = new ArrayList<>();
// 每輪執行 n + 1 個任務
for (int i = 0; i < n + 1; i++) {
if (queue.size() > 0) {
time++;
char c = queue.poll();
// 還有次數放入temp,結束的時候再一起放回佇列
if (--counts[c - 'A'] > 0) {
temp.add(c);
}
} else {
// temp為空,說明是最後一輪,最後一輪不需要(待命)
if (temp.size() > 0) {
time++;
}
}
}
queue.addAll(temp);
}
return time;
}
方法二:構造
因為同類任務最少間隔 n,一輪任務就是 n + 1 的時間。設最多的任務需要執行 m 次,不考慮最後一輪的情況,前面一共需要 ( m - 1) * (n + 1) 的時間。下面分析最後一輪可能的情況
- 最後一輪還剩下的任務,任務次數必然只有一次
- 前面的 m - 1 輪中出現過「待命」:說明最後一輪的任務只剩下總次數為 m 的任務(總次數為 m 的任務可能不止一個),假設總次數為 m 的任務為 k 個。總的時間即為 ( m - 1) * (n + 1) + k 。
- 前面的 m - 1 輪中沒有出現過「待命」:因為最後一輪必然不會出現「待命」,總的時間就是 tasks.length 唄。
綜上:總的時間為 max(( m - 1) * (n + 1) + k, tasks.length)。
public int leastInterval(char[] tasks, int n) {
if (n == 0) {
return tasks.length;
}
// 統計每個任務的次數
int[] counts = new int[26];
for (char ch : tasks) {
counts[ch - 'A']++;
}
// maxExec 最多的任務的次數
// maxCount 有maxExec次的任務有多少個
int maxExec = 0, maxCount = 0;
for (int i = 0; i < 26; i++) {
if (counts[i] > maxExec) {
maxExec = counts[i];
maxCount = 1;
} else if (counts[i] == maxExec) {
maxCount++;
}
}
return Math.max((maxExec - 1) * (n + 1) + maxCount, tasks.length);
}
執行結果
相關文章
- LeetCode每日一題--621. 任務排程器(雜湊表)LeetCode每日一題
- 力扣-621. 任務排程器力扣
- 力扣 621. 任務排程器力扣
- 621. 任務排程器 (構造)
- LeetCode 621 任務排程器LeetCode
- 任務排程
- Airflow 任務排程AI
- Laravel 任務排程Laravel
- 分散式任務排程分散式
- Spring 指南(排程任務)Spring
- Spark中資源排程和任務排程Spark
- Aloha:一個分散式任務排程框架分散式框架
- Timer和TimerTask 任務排程
- 聊聊PowerJob的任務排程
- Linux 定時任務排程Linux
- 分散式排程任務-ElasticJob分散式AST
- laravel框架任務排程(定時執行任務)Laravel框架
- leetcode每日一題LeetCode每日一題
- 新一代分散式任務排程框架分散式框架
- 一文詳解 Linux Crontab 排程任務Linux
- 比特幣原始碼分析:任務排程器的使用比特幣原始碼
- Windows 10任務排程器曝出新零日漏洞Windows
- Python任務排程模組APSchedulerPython
- LTS分散式任務排程部署分散式
- 用海豚排程器定時排程從Kafka到HDFS的kettle任務指令碼Kafka指令碼
- 基於Hyperf開發的任務排程系統.支援任務投遞,DAG任務編排(多個任務使用同一個事務).
- 一文快速入門任務排程框架-Quartz框架quartz
- 深入 Java Timer 定時任務排程器實現原理Java
- 使用寶塔計劃任務啟動laravel排程器Laravel
- Leetcode每日一題(1)LeetCode每日一題
- LiteOS-任務篇-原始碼分析-任務排程函式原始碼函式
- Spring排程定時任務的方式Spring
- Android 中的定時任務排程Android
- 任務排程的思考和總結
- Flink - Task 任務排程執行流程
- 任務排程框架Quartz快速入門!框架quartz
- iOS 任務排程器:為 CPU 和記憶體減負iOS記憶體
- 今天,總監說要一個任務排程的列表。