The most frequent task forces a minimum frame size on the schedule. Count frequencies, find the max, then a single (maxCount - 1) * (n + 1) + numMax formula gives the answer — no simulation needed.
Given a list of tasks (uppercase letters) and a cooldown n, return the minimum number of CPU intervals needed to finish all tasks. The same task type must be at least n intervals apart; idle slots are allowed.
Example: tasks = ["A","A","A","B","B","B"], n = 2. The answer is 8. One optimal schedule: A B idle A B idle A B — A and B each appear 3 times, cooldown 2, two idle slots required.
maxCount) creates maxCount - 1mandatory "gaps" between its executions. Each gap must be at least n wide. So the minimum time is (maxCount - 1) * (n + 1) + numMax, where numMax counts how many tasks share that max frequency. But if there are so many distinct tasks that they fill all gaps without idle time, the answer is just tasks.length.tasks and build a frequency map. We only care about the counts, not which letter is which.maxCount? Each of them fills the last partial frame.(maxCount - 1) * (n + 1) + numMax. This is the length of the schedule if idle slots are needed: maxCount - 1 full frames of width n + 1, plus the final partial frame of width numMax.Math.max(formula, tasks.length). If tasks are so numerous that they pack all gaps, no idle time is needed and the answer equals the raw task count.Because tasks are uppercase letters, the frequency map has at most 26 entries — O(1)space in practice. The formula approach is the one to code in an interview; the simulation is worth knowing as the "how would you prove it?" follow-up.
6 tasks total, cooldown n = 2.1▶function leastInterval(tasks: string[], n: number): number {2 // Count task frequencies3▶ const freq = new Map<string, number>();4 for (const t of tasks) freq.set(t, (freq.get(t) ?? 0) + 1);56 // Find maximum frequency and how many tasks share it7 let maxCount = 0;8 for (const v of freq.values()) maxCount = Math.max(maxCount, v);9 let numMax = 0;10 for (const v of freq.values()) if (v === maxCount) numMax++;1112 // Greedy formula: (maxCount - 1) gaps of size (n + 1), plus tasks that share max13 const formula = (maxCount - 1) * (n + 1) + numMax;1415 // If tasks are dense enough they fill every idle slot, no idle needed16 return Math.max(formula, tasks.length);17}
function leastInterval(tasks: string[], n: number): number {
// Count task frequencies
const freq = new Map<string, number>();
for (const t of tasks) freq.set(t, (freq.get(t) ?? 0) + 1);
// Find maximum frequency and how many tasks share it
let maxCount = 0;
for (const v of freq.values()) maxCount = Math.max(maxCount, v);
let numMax = 0;
for (const v of freq.values()) if (v === maxCount) numMax++;
// Greedy formula: (maxCount - 1) gaps of size (n + 1), plus tasks that share max
const formula = (maxCount - 1) * (n + 1) + numMax;
// If tasks are dense enough they fill every idle slot, no idle needed
return Math.max(formula, tasks.length);
}Map<string, number> works; so would a number[26] fixed array. The ?? 0 handles the first occurrence.freq.values(). This is the bottleneck count — the task type that runs the most often determines how many gaps we must space out.(maxCount - 1) full frames, each of width n + 1 (one task + n cooldown slots), plus the last partial frame of numMax tasks. This equals the minimum time if idle slots are needed.tasks.length is the true answer. Math.max picks whichever is larger — idle slots can never make the schedule shorter than the raw count.n intervals.tasks.length. The formula still gives the right answer: (maxCount - 1) * 1 + numMax ≤ tasks.length.function leastInterval(tasks: string[], n: number): number {
// Count task frequencies
const freq = new Map<string, number>();
for (const t of tasks) freq.set(t, (freq.get(t) ?? 0) + 1);
// Find maximum frequency and how many tasks share it
let maxCount = 0;
for (const v of freq.values()) maxCount = Math.max(maxCount, v);
let numMax = 0;
for (const v of freq.values()) if (v === maxCount) numMax++;
// Greedy formula: (maxCount - 1) gaps of size (n + 1), plus tasks that share max
const formula = (maxCount - 1) * (n + 1) + numMax;
// If tasks are dense enough they fill every idle slot, no idle needed
return Math.max(formula, tasks.length);
}Forget the formula: actually run the clock. Each interval, pick the available task with the highest remaining count, mark it on cooldown for the next n slots, and count every tick (including forced idles) until all tasks are done.
function leastInterval(tasks: string[], n: number): number {
const freq = new Array<number>(26).fill(0);
for (const t of tasks) freq[t.charCodeAt(0) - 65]++;
// cooldown[i] = the next interval at which task i is allowed to run again.
const cooldown = new Array<number>(26).fill(0);
let remaining = tasks.length;
let time = 0;
while (remaining > 0) {
time++;
// Among tasks with work left AND off cooldown, pick the most frequent.
let best = -1;
for (let i = 0; i < 26; i++) {
if (freq[i] > 0 && cooldown[i] <= time) {
if (best === -1 || freq[i] > freq[best]) best = i;
}
}
if (best === -1) continue; // everything is cooling down -> idle this slot
freq[best]--;
remaining--;
cooldown[best] = time + n + 1; // can't reuse until n slots have passed
}
return time;
}(maxCount-1)*(n+1)+numMax computes in O(n) with no loop at all. Use the simulation only when you must emit the actual ordering, not just its length.| "cooldown / n intervals apart" + minimize total time | frequency count + (maxCount-1)*(n+1)+numMax formula |
| most frequent element constrains spacing | find maxCount, count ties |
| answer is max(formula, input size) | formula floor = tasks.length when tasks are dense |
| "reorganize / rearrange string" variants | same frequency-bottleneck idea |
function leastInterval(tasks: string[], n: number): number {
const freq = new Map<string, number>();
for (const t of tasks) freq.set(t, (freq.get(t) ?? 0) + 1);
let maxCount = 0;
for (const v of freq.values()) maxCount = Math.max(maxCount, v);
let numMax = 0;
for (const v of freq.values()) if (v === maxCount) numMax++;
const formula = (maxCount - 1) * (n + 1) + numMax;
return Math.max(formula, tasks.length);
}tasks = ["A","A","A","B","B","B"] and n = 2, what is the minimum number of intervals?tasks = ["A","A","A","B","B","B","C","C","C","D","D","E"] and n = 2, the answer is:Math.max(formula, tasks.length) rather than just returning the formula?