Task Scheduler — Leetcode 621
2 min readDec 18, 2022
Original problem link: https://leetcode.com/problems/task-scheduler/description/
In this problem, we’re asked to calculate the minimum time needed to finish all the tasks (which take 1 time unit each) in an array, given a cooldown time of n units between the same tasks (that can be filled by other different tasks).
We can find the answer directly using math. The intuition behind my solution is to find the max frequency of any tasks and the number of such tasks with the max frequency. Then we distribute the rest of the tasks evenly on each cycle, and pad each cycle with idle time units if necessary. Each variable has a comment on it explaining its meaning.
class Solution {
public int leastInterval(char[] tasks, int n) {
if (n == 0) {
return tasks.length;
}
Map<Character, Integer> taskMap = new HashMap<>();
// highest frequency of the same task appearing
int maxFrequency = 0;
for (char task : tasks) {
taskMap.put(task, taskMap.getOrDefault(task, 0) + 1);
maxFrequency = Math.max(taskMap.get(task), maxFrequency);
}
// number of such max frequency tasks
int maxFreqTasks = 0;
for (char task : taskMap.keySet()) {
if (taskMap.get(task) == maxFrequency) {
maxFreqTasks++;
}
}
// rest of the tasks
int nonMaxFreqTasks = tasks.length - (maxFreqTasks * maxFrequency);
// rest of the distributed tasks on each cycle
int cycleLength = maxFrequency > 1 ? (nonMaxFreqTasks / (maxFrequency - 1)) : 0;
// extra tasks distributed to the first few cycles if any
int remaining = maxFrequency > 1 ? (nonMaxFreqTasks % (maxFrequency - 1)) : 0;
// total length of each cycle (minus remaining)
int cycle = maxFreqTasks + cycleLength;
int idle = 0;
// distribute idles if needed
if (cycle + 1 <= n && remaining > 0) {
idle += ((maxFrequency - 1) * (n - cycle));
} else if (cycle <= n && remaining == 0) {
idle += ((maxFrequency - 1) * (n - cycle + 1));
}
// add extra idles for the cycles that didn't get the "remaining" tasks
if (remaining > 0 && cycle <= n) {
idle += (maxFrequency - 1 - remaining);
}
return tasks.length + idle;
}
}