Many LeetCode problems involve scheduling, focusing on optimizing resource use and minimizing completion time, whether it's for job scheduling, CPU scheduling, or project durations. The goal is to efficiently utilize resources to enhance productivity and reduce costs across various applications. The Task Scheduler problem introduces an added complexity: a cooling period between identical tasks. This constraint requires careful planning to respect cooldown periods while still optimizing resource use and minimizing overall completion time, reflecting the real-world challenges faced in task management systems.
Given a character array tasks
, where each character represents a unique task and a positive integer n
that represents the cooling period between any two identical tasks, find the minimum number of time units the CPU will need to complete all the given tasks. Each task requires one unit to perform, and the CPU must wait for at least n
units of time before it can repeat the same task. During the cooling period, the CPU can perform other tasks or remain idle.
Constraints:
tasks.length
n
tasks
consists of uppercase English letters
Let’s take a look at a few examples to get a better understanding of the problem statement:
Let’s take a moment to ensure you’ve correctly understood the problem. The quiz below helps you check if you’re solving the correct problem.
Task Scheduler
What’s the minimum number of units of time if the following values are given as input?
Tasks = [A, A, A, B, B, C, C]
n = 1
3
7
8
9
An optimal strategy is to schedule the most frequent task first, then the second most frequent task, and so on. This is because once we’ve scheduled the most frequent task, we can get an estimate of the maximum idle time. Therefore, we keep track of the frequencies of all tasks using a hash map, frequencies
. Let’s say we have tasks
= n
= 2, then frequencies
=
Next, we utilize these idle slots to schedule the remaining tasks. The next most frequent task is
Finally, we can schedule task tasks
= n
= 2.
The formula above works fine as long as
For example, tasks
= n
=
In general, the total time required by the CPU can be calculated as:
Let’s look at the following illustration to get a better understanding of the solution:
Let’s look at the code for the algorithm we just discussed.
def least_time(tasks, n):# initialize a dictionary to store the frequencies of the tasksfrequencies = {}# store the frequency of each taskfor t in tasks:frequencies[t] = frequencies.get(t,0) + 1# sort the frequenciesfrequencies = dict(sorted(frequencies.items(), key=lambda x:x[1]))# store the max frequencymax_freq = frequencies.popitem()[1]# compute the maximum possible idle timeidle_time = (max_freq - 1) * n# iterate over the freqencies array and update the idle timewhile frequencies and idle_time > 0:idle_time -= min(max_freq - 1, frequencies.popitem()[1])idle_time = max(0, idle_time)# return the total time, which is the sum of the busy time and idle timereturn len(tasks) + idle_time# driver codedef main():all_tasks = [['A', 'A', 'B', 'B'],['A', 'A', 'A', 'B', 'B', 'C', 'C'],['S', 'I', 'V', 'U', 'W', 'D', 'U', 'X'],['M', 'A', 'B', 'M', 'A', 'A', 'Y', 'B', 'M'],['A', 'K', 'X', 'M', 'W', 'D', 'X', 'B', 'D', 'C', 'O', 'Z', 'D', 'E', 'Q']]all_ns = [2, 1, 0, 3, 3]for i in range(len(all_tasks)):print(i+1, '.', '\tTasks: ', all_tasks[i], sep='')print('\tn: ', all_ns[i], sep='')min_time = least_time(all_tasks[i], all_ns[i])print('\tMinimum time required to execute the tasks: ', min_time)print('-' * 100)if __name__ == '__main__':main()
Let’s analyze the time and space complexity of our solution.
The time complexity of counting the frequencies of tasks is
The space complexity is
Free Resources