Example 1
ready- Input
tasks = [ "A", "A", "A", "B", "B", "B" ] n = 2- Expected
8- Why
- A B idle A B idle A B finishes in 8 time units
A processor can finish one task per tick, but repeating the same task type too soon overheats its worker. Other tasks can fill the wait; when none fit, the processor idles.
You're given tasks, where each single uppercase letter names a task type. You're also
given a cooldown n, the minimum number of intervening time slots required between
two copies of the same task.
Choose any execution order and return the fewest total time units needed to finish every task. Both task executions and idle slots count toward the total.
A few ground rules:
n = 0, identical tasks may run back to back.1 <= tasks.length <= 100_000tasks[i] is one uppercase letter from A through Z.0 <= n <= 100Hints
If one task appears far more often than the others, it creates the idle pressure. A max-heap can repeatedly choose the available type with the most copies left.
Suppose the highest frequency is maxFreq. Place those copies first. The first
maxFreq - 1 copies each start a block that needs n following slots before the
next copy may appear.
If numMax task types share the maximum frequency, the last block contains all
numMax of them. Compare (maxFreq - 1) * (n + 1) + numMax with tasks.length.
The formula gives only the minimum length. How would you construct one valid schedule with that length, including its idle slots?
Visible cases
tasks = [
"A",
"A",
"A",
"B",
"B",
"B"
]
n = 28tasks = [
"A",
"A",
"A",
"B",
"B",
"B"
]
n = 06tasks = [
"A",
"A",
"A",
"B",
"B",
"B",
"C",
"C"
]
n = 28Interview signal
Count each task type, then keep the available counts in a max-heap. At every time unit, run the available type with the most work left. A cooldown queue records when that type may return to the heap.
from collections import Counter, deque
import heapq
def least_interval(tasks: list[str], n: int) -> int:
available = [-count for count in Counter(tasks).values()]
heapq.heapify(available)
cooling: deque[tuple[int, int]] = deque()
time = 0
while available or cooling:
while cooling and cooling[0][0] <= time:
_, count = cooling.popleft()
heapq.heappush(available, count)
if available:
count = heapq.heappop(available) + 1
if count < 0:
cooling.append((time + n + 1, count))
time += 1
return timeChoosing the most frequent available type leaves the widest chance to fit its future copies around other work. The simulation is useful when you also need the actual schedule, but long idle stretches make it do work for time units that run no task.
Let T be the returned number of time units and m = len(tasks).
Time O(T log 26), space O(1) because there are only 26 task types.
Only the busiest task types can force idle time. Let:
max_frequency be the largest count of any task type, andnumber_at_max be how many task types have that count.The first max_frequency - 1 copies of a busiest type each begin a block of width
n + 1: one task plus n separating slots. The last block needs one position for each
type tied at the maximum. That gives:
(max_frequency - 1) * (n + 1) + number_at_max
Other tasks may fill every gap and make idle time disappear, so the answer can never be
smaller than len(tasks). Take the larger quantity.
from collections import Counter
def least_interval(tasks: list[str], n: int) -> int:
frequencies = list(Counter(tasks).values())
max_frequency = max(frequencies)
number_at_max = sum(
count == max_frequency for count in frequencies
)
forced_length = (max_frequency - 1) * (n + 1) + number_at_max
return max(len(tasks), forced_length)When enough different work exists, len(tasks) wins and every slot runs a task. When
one type dominates, the block calculation wins and the difference is forced idle time.
Time O(m), space O(1) for counting m tasks across a fixed 26-letter alphabet.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
8