Task Scheduler

Solution For Task Scheduler

Problem Statement:

You are given a list of tasks that need to be executed, each with a fixed start time and duration. Given a non-negative integer n that represents the cooldown period between two tasks of the same type, return the minimum number of CPU intervals needed to execute all the given tasks.

Example:

Input: tasks = [“A”,”A”,”A”,”B”,”B”,”B”], n = 2

Output: 8

Explanation:
A -> B -> idle -> A -> B -> idle -> A -> B

Approach:

To solve this problem, we can use a greedy approach. First, we need to count the frequency of each task. Then, we sort the tasks in decreasing order of their frequency. We also maintain a list of cooldowns for each task. Initially, all the cooldowns are 0.

We start processing the tasks in the order of their frequency. For each task, we find the task with the maximum cooldown. If the maximum cooldown is greater than 0, we wait for that many intervals before processing the current task. If the maximum cooldown is 0, we can process the current task immediately.

After processing the current task, we update the cooldown of all the tasks. The cooldown of the current task is set to n+1 (n is the given cooldown period). This is because we need to leave a gap of n intervals before processing the same task again. The cooldown of all the other tasks is reduced by 1.

We repeat this process until all the tasks are processed.

Code:

class Solution {
public:
int leastInterval(vector<char>& tasks, int n) {
unordered_map<char, int> freq;
for (char t : tasks) {
freq[t]++;
}
auto cmp = [&](char a, char b) {
return freq[a] < freq[b];
};
priority_queue<char, vector<char>, decltype(cmp)> pq(cmp);
for (auto p : freq) {
pq.push(p.first);
}
vector<int> cooldown(26, 0);
int intervals = 0;
while (!pq.empty()) {
vector<char> available;
while (!pq.empty()) {
char t = pq.top();
pq.pop();
if (cooldown[t-'A'] == 0) {
available.push_back(t);
break;
}
}
if (available.empty()) {
intervals++;
} else {
char t = available.front();
available.erase(available.begin());
freq[t]--;
cooldown[t-'A'] = n+1;
for (char c : available) {
cooldown[c-'A']--;
}
if (freq[t] > 0) {
pq.push(t);
}
intervals++;
}
for (int i = 0; i < 26; i++) {
if (cooldown[i] > 0) {
cooldown[i]--;
}
}
}
return intervals;
}
};

Time Complexity:

The time complexity of this solution is O(nlogn), where n is the number of tasks. The sorting of tasks takes O(nlogn) time, and for each task, we can spend at most O(logn) time in the priority queue. Since we process each task exactly once, the total time complexity is O(nlogn).

Step by Step Implementation For Task Scheduler

class Solution {
    public int leastInterval(char[] tasks, int n) {
        int[] map = new int[26];
        for (char c: tasks)
            map[c - 'A']++;
        Arrays.sort(map);
        int max_val = map[25] - 1, idle_slots = max_val * n;
        for (int i = 24; i >= 0 && map[i] > 0; i--) {
            idle_slots -= Math.min(map[i], max_val);
        }
        return idle_slots > 0 ? idle_slots + tasks.length : tasks.length;
    }
}
There are a total of n tasks you have to pick, labeled from 0 to n-1. Some tasks may have dependencies, i.e. they need to be done before others. 

Given the number of tasks and a list of dependencies, return a sequence of tasks you need to pick to finish all tasks.

You may assume that there will be no circular dependencies.

 

Example 1:

Input: n = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
Output: [0,1,2,3] or [0,2,1,3]
Explanation: There are a total of 4 tasks. You can do them in any order, but you should make sure to do task 0 first.

def findOrder(numCourses, prerequisites):

    #Create a graph and add edges
    graph = collections.defaultdict(list)
    for u, v in prerequisites:
        graph[u].append(v)

    #Create a visited set to keep track of visited nodes
    visited = set()

    #Create a stack to keep track of the order of nodes
    stack = []

    #Create a function to do a depth first search
    def dfs(node):
        if node in visited:
            return False
        visited.add(node)
        for neighbor in graph[node]:
            if not dfs(neighbor):
                return False
        stack.append(node)
        return True

    #Do a depth first search for all nodes
    for i in range(numCourses):
        if not dfs(i):
            return []
    return stack[::-1]
var leastInterval = function(tasks, n) {
    // create a hashmap to store the count of each task
    let map = {};
    for(let t of tasks){
        map[t] = (map[t]||0) + 1;
    }
    // sort the tasks according to their count in descending order
    let sortable = [];
    for(let t in map){
        sortable.push([t, map[t]]);
    }
    sortable.sort((a,b) => {
        return b[1] - a[1];
    });
    // find the maximum count
    let maxCount = sortable[0][1];
    // find the number of tasks with maximum count
    let maxTasks = 0;
    for(let i = 0; i < sortable.length; i++){
        if(sortable[i][1] == maxCount){
            maxTasks++;
        }
    }
    // the minimum number of intervals needed is equal to the maximum count of any task plus the number of tasks with that maximum count minus 1, all multiplied by n plus 1
    return Math.max((maxCount - 1) * (n + 1) + maxTasks, tasks.length);
};
class Solution {
public:
    int leastInterval(vector& tasks, int n) {
        // Create a map of task counts
        unordered_map taskCounts;
        for (char c : tasks) {
            taskCounts[c]++;
        }
        
        // Sort the task counts in descending order
        priority_queue pq;
        for (auto it : taskCounts) {
            pq.push(it.second);
        }
        
        // Perform the scheduling
        int intervalCount = 0;
        while (!pq.empty()) {
            // Schedule up to n tasks at a time
            vector scheduledTasks;
            for (int i = 0; i <= n; i++) {
                if (!pq.empty()) {
                    scheduledTasks.push_back(pq.top());
                    pq.pop();
                }
            }
            
            // Add the scheduled tasks back to the queue
            for (int count : scheduledTasks) {
                if (--count > 0) {
                    pq.push(count);
                }
            }
            
            // Add n+1 to the interval count (if there are more tasks to schedule)
            // or add the number of scheduled tasks (if there are no more tasks to schedule)
            intervalCount += pq.empty() ? scheduledTasks.size() : n + 1;
        }
        
        return intervalCount;
    }
};
public class Solution {
    public int LeastInterval(char[] tasks, int n) {
        // Create a frequency map of all the tasks
        var taskFrequencyMap = new Dictionary();
        foreach(var task in tasks)
        {
            if(taskFrequencyMap.ContainsKey(task))
            {
                taskFrequencyMap[task]++;
            }
            else
            {
                taskFrequencyMap.Add(task, 1);
            }
        }
        
        // Sort the tasks by frequency (most frequent first)
        var sortedTasks = taskFrequencyMap.OrderByDescending(t => t.Value).Select(t => t.Key).ToList();
        
        // Initialize the result
        var result = 0;
        
        // Loop through the tasks
        while(sortedTasks.Count > 0)
        {
            // Initialize the current task list
            var currentTasks = new List();
            
            // Add the most frequent task to the current task list
            currentTasks.Add(sortedTasks[0]);
            
            // Remove the most frequent task from the sorted task list
            sortedTasks.RemoveAt(0);
            
            // Loop through the remaining tasks
            for(int i = 0; i < sortedTasks.Count; i++)
            {
                // If the current task list is not full
                if(currentTasks.Count < n + 1)
                {
                    // Add the next task to the current task list
                    currentTasks.Add(sortedTasks[i]);
                    
                    // Remove the task from the sorted task list
                    sortedTasks.RemoveAt(i);
                    
                    // Decrement the index so that we don't skip a task
                    i--;
                }
                else
                {
                    // Break out of the loop, we don't need to process any more tasks
                    break;
                }
            }
            
            // If the sorted task list is empty, we can just return the result
            if(sortedTasks.Count == 0)
            {
                return result + currentTasks.Count;
            }
            
            // Otherwise, we need to update the frequencies of the tasks that we processed
            foreach(var task in currentTasks)
            {
                taskFrequencyMap[task]--;
            }
            
            // Add the current task list count to the result
            result += currentTasks.Count;
            
            // Sort the tasks by frequency (most frequent first)
            sortedTasks = taskFrequencyMap.Where(t => t.Value > 0).OrderByDescending(t => t.Value).Select(t => t.Key).ToList();
        }
        
        return result;
    }
}


Scroll to Top

Top 100 Leetcode Practice Problems In Java

Get 30% Off Instantly!
[gravityforms id="5" description="false" titla="false" ajax="true"]