Task Schedular
LeetCode Problem
# https://leetcode.com/problems/task-scheduler/
"""
AAABBCC
Hashmap : {A : 3, B : 2, C : 2}
n (waiting time) = 1
Best to pick most frequent character first so we're never idle even in waiting time
If we pick C first
CBCBA_A_A_A = NAHHHH : 9
Pick A first
ABCABCA : minimises the IDLE time : 7
MaxHeap : Configure which task if frequent : O(log(26))
Count occurence of each task and pop and add to maxHeap : O(n)
Time : n + time to process (1 second per task)
Queue to add task and time
"""
import heapq
# Time : O(n(log(n))) Space : O(n) (Counter takes nlogn)
# Round Robin technique (queue needed for tasks which are waiting for cool down period)
# Iterate till all the tasks are processed.
# Pick the task from heap having the maximum frequency.
# Since only one task can be processed in a unit time. So process the task. frequency -= 1
# Now if this task is left then it will have to wait for the cooldown period.
# So, add queue the task till its cooldown period is expired. (cooldown period : time taken by task + n)
# At end : process the tasks whose cooling period is expired.
from collections import deque
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
if n == 0:
return len(tasks) # no waiting time
hashmap = Counter(tasks)
heap = [-val for val in hashmap.values()]
heapq.heapify(heap)
queue = deque() # [frequency, time_at_which_it_can_start_executing] # hold tasks which are waiting for cool down period
time_taken = 0
while heap or queue: # iterate till all tasks processed (round robin)
time_taken += 1
# pick task with max freq
if heap:
frequency = -heapq.heappop(heap)
# since only one task can be processed in unit time : process this task and update freq
frequency -= 1
# if task still left : put it in waiting queue and continue round robin
if frequency:
queue.append(
[frequency, time_taken + n]
) # enque task till it's cooldown period
# process tasks whose cooling period is expired (waiting queue tasks)
while queue and queue[0][1] == time_taken:
heapq.heappush(
heap, -queue.popleft()[0]
) # only pop the frequncy (3 or 2 or 1 of letters)
return time_taken