Task Scheduler
Schedule tasks with a cooldown using a math identity on the most-frequent task.
Problem#
Each task takes one unit of time; identical tasks must be separated by at least n time units of cooldown. Return the minimum total time.
Examples#
tasks = ["A","A","A","B","B","B"], n = 2→8tasks = ["A","C","A","B","D","B"], n = 1→6
Constraints#
1 <= tasks.length <= 10^4,0 <= n <= 100.
Hints#
Hint 1
Approach#
Let maxFreq be the highest count and ties the number of tasks tied at that count. Frame: place maxFreq - 1 blocks of size n + 1 followed by ties trailing tasks. The answer is max(len(tasks), (maxFreq - 1) * (n + 1) + ties).
Solution#
class Solution {public: int leastInterval(vector<char>& tasks, int n) { int cnt[26] = {0}; for (char c : tasks) ++cnt[c - 'A']; int maxFreq = *max_element(cnt, cnt + 26); int ties = count(cnt, cnt + 26, maxFreq); return max((int)tasks.size(), (maxFreq - 1) * (n + 1) + ties); }};func leastInterval(tasks []byte, n int) int { cnt := [26]int{} for _, c := range tasks { cnt[c-'A']++ } maxFreq := 0 for _, v := range cnt { if v > maxFreq { maxFreq = v } } ties := 0 for _, v := range cnt { if v == maxFreq { ties++ } } candidate := (maxFreq-1)*(n+1) + ties if len(tasks) > candidate { return len(tasks) } return candidate}from collections import Counterfrom typing import List
class Solution: def leastInterval(self, tasks: List[str], n: int) -> int: cnt = Counter(tasks) max_freq = max(cnt.values()) ties = sum(1 for v in cnt.values() if v == max_freq) return max(len(tasks), (max_freq - 1) * (n + 1) + ties)var leastInterval = function(tasks, n) { const cnt = new Array(26).fill(0); for (const c of tasks) cnt[c.charCodeAt(0) - 65]++; const maxFreq = Math.max(...cnt); const ties = cnt.filter(v => v === maxFreq).length; return Math.max(tasks.length, (maxFreq - 1) * (n + 1) + ties);};class Solution { public int leastInterval(char[] tasks, int n) { int[] cnt = new int[26]; for (char c : tasks) cnt[c - 'A']++; int maxFreq = 0; for (int v : cnt) if (v > maxFreq) maxFreq = v; int ties = 0; for (int v : cnt) if (v == maxFreq) ties++; return Math.max(tasks.length, (maxFreq - 1) * (n + 1) + ties); }}function leastInterval(tasks: string[], n: number): number { const cnt: number[] = new Array(26).fill(0); for (const c of tasks) cnt[c.charCodeAt(0) - 65]++; const maxFreq: number = Math.max(...cnt); const ties: number = cnt.filter((v: number) => v === maxFreq).length; return Math.max(tasks.length, (maxFreq - 1) * (n + 1) + ties);}Editorial#
Picture the schedule as a grid: maxFreq rows of length n + 1 (one execution + n cooldown), with the last row possibly shorter. The most-frequent task fills the leftmost column; ties also each fill one column. Empty cells in the grid are idle. If the rest of the tasks can fit in the idle cells, total time is the grid size; otherwise it’s tasks.size() (no idleness needed). The max handles both cases.
Complexity#
- Time: O(n).
- Space: O(1).
Concept revision#
Related#