Task Scheduler
Given an array of CPU tasks, each labeled by a letter, and an integer n representing the required cooldown between two occurrences of the same task, return the minimum number of intervals needed to finish all tasks. A CPU may sit idle if no task is eligible yet. The most-frequent task drives the answer : space it out by its required cooldown, and any idle slots left over get filled by other tasks or otherwise stay idle.
Constraints
- 1 ≤ tasks.length ≤ 104
- tasksi is an uppercase English letter
- 0 ≤ n ≤ 100
Example
tasks = ["A", "A", "A", "B", "B", "B"], n = 28Explanation One valid order is A, B, idle, A, B, idle, A, B — 8 intervals, respecting the cooldown of 2 for each letter.
In plain terms
- Cooldown
- The minimum number of intervals that must pass before the same task letter can run again.
Space out the most frequent tasks by the cooldown
Both A and B occur 3 times — that is the highest frequency in this task list.
What happens in this step
freq: A = 3, B = 3 maxCount = max(3, 3) = 3 — both A and B tie for the highest frequency in this task list.
Steps to visualize
- Count how often each task letter appears.
- Find the highest count, and how many different letters share that highest count.
- The busiest tasks need (maxCount - 1) full cooldown rows, plus one slot per tied task in the final row.
- The answer is whichever is larger: that reserved slot count, or simply the total number of tasks.
Walk through the code
Same walkthrough, now with the code. Press Next to move one step and watch which lines run.
Both A and B occur 3 times — that is the highest frequency in this task list.
What happens in this step
freq: A = 3, B = 3 maxCount = max(3, 3) = 3 — both A and B tie for the highest frequency in this task list.
Solution
function leastInterval(tasks, n) {
const freq = new Map();
for (const task of tasks) {
freq.set(task, (freq.get(task) ?? 0) + 1);
}
const counts = [...freq.values()];
const maxCount = Math.max(...counts);
const maxCountTasks = counts.filter((count) => count === maxCount).length;
return Math.max(tasks.length, (maxCount - 1) * (n + 1) + maxCountTasks);
}- Time
- O(n)
- Space
- O(1)
Test cases
| Input | Expected | Covers |
|---|---|---|
tasks = ["A", "A", "A", "B", "B", "B"], n = 2 | 8 | example from the docstring |
tasks = ["A", "A", "A", "B", "B", "B"], n = 0 | 6 | no cooldown means tasks can run back to back |
tasks = ["A", "A", "A", "A", "A", "A", "B", "C", "D", "E", "F", "G"], n = 2 | 16 | one task dominates heavily while others just fill idle slots |
tasks = ["A", "A", "A"], n = 2 | 7 | only one task type, forcing idle slots for the full cooldown |
tasks = ["A", "B", "C", "D"], n = 2 | 4 | every task is different, so no cooldown ever applies |
tasks = ["A", "A", "B", "B"], n = 0 | 4 | zero cooldown always equals the raw task count |
tasks = ["A"], n = 5 | 1 | smallest valid input, a single task with no repeats to space out |