LeetCodee

621. Task Scheduler

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

Given a characters array tasks, representing the tasks a CPU needs to do, where each letter represents a different task. Tasks could be done in any order. Each task is done in one unit of time. For each unit of time, the CPU could complete either one task or just be idle.

However, there is a non-negative integer n that represents the cooldown period between two same tasks (the same letter in the array), that is that there must be at least n units of time between any two same tasks.

Return the least number of units of time that the CPU will take to finish all the given tasks.

Examples:

Example 1:

Input: tasks = ["A","A","A","B","B","B"], n = 2
Output: 8
Explanation: 
A -> B -> idle -> A -> B -> idle -> A -> B
There is at least 2 units of time between any two same tasks.

Example 2:

Input: tasks = ["A","A","A","B","B","B"], n = 0
Output: 6
Explanation: On this case any permutation of size 6 would work since n = 0.
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
etc.

Example 3:

Input: tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
Output: 16
Explanation: 
One possible solution is
A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> idle -> idle -> A -> idle -> idle -> A

Constraints:

  • 1 <= task.length <= 10⁴
  • tasks[i] is upper-case English letter
  • 0 <= n <= 100

Solution

Python Solution

class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        # Count frequency of each task
        freq = Counter(tasks)
        max_freq = max(freq.values())
        
        # Count how many tasks have the maximum frequency
        max_freq_tasks = sum(1 for f in freq.values() if f == max_freq)
        
        # Calculate minimum intervals needed
        min_intervals = (max_freq - 1) * (n + 1) + max_freq_tasks
        
        return max(min_intervals, len(tasks))

Time Complexity: O(N)

Where N is the number of tasks.

Space Complexity: O(1)

Since we only store at most 26 characters (uppercase English letters).

Explanation:

  1. Count the frequency of each task
  2. Find the task with maximum frequency (max_freq)
  3. Count tasks with maximum frequency (max_freq_tasks)
  4. Calculate minimum intervals using formula: (max_freq - 1) * (n + 1) + max_freq_tasks
  5. Return maximum of calculated intervals and total tasks

Java Solution

class Solution {
    public int leastInterval(char[] tasks, int n) {
        // Count frequency of each task
        int[] freq = new int[26];
        for (char task : tasks) {
            freq[task - 'A']++;
        }
        
        // Find maximum frequency
        int maxFreq = 0;
        for (int f : freq) {
            maxFreq = Math.max(maxFreq, f);
        }
        
        // Count tasks with maximum frequency
        int maxFreqTasks = 0;
        for (int f : freq) {
            if (f == maxFreq) maxFreqTasks++;
        }
        
        // Calculate minimum intervals needed
        int minIntervals = (maxFreq - 1) * (n + 1) + maxFreqTasks;
        
        return Math.max(minIntervals, tasks.length);
    }
}

Alternative Solution using PriorityQueue:

class Solution {
    public int leastInterval(char[] tasks, int n) {
        int[] freq = new int[26];
        for (char task : tasks) {
            freq[task - 'A']++;
        }
        
        PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a);
        for (int f : freq) {
            if (f > 0) pq.offer(f);
        }
        
        int time = 0;
        while (!pq.isEmpty()) {
            List temp = new ArrayList<>();
            int i = 0;
            
            while (i <= n && !pq.isEmpty()) {
                int count = pq.poll();
                if (count > 1) temp.add(count - 1);
                time++;
                i++;
            }
            
            pq.addAll(temp);
            if (!pq.isEmpty() && i <= n) time += (n - i + 1);
        }
        
        return time;
    }
}

C++ Solution

class Solution {
public:
    int leastInterval(vector& tasks, int n) {
        vector freq(26, 0);
        for (char task : tasks) {
            freq[task - 'A']++;
        }
        
        int maxFreq = *max_element(freq.begin(), freq.end());
        int maxFreqTasks = count(freq.begin(), freq.end(), maxFreq);
        
        int minIntervals = (maxFreq - 1) * (n + 1) + maxFreqTasks;
        
        return max(minIntervals, (int)tasks.size());
    }
};

Alternative Solution using Priority Queue:

class Solution {
public:
    int leastInterval(vector& tasks, int n) {
        vector freq(26, 0);
        for (char task : tasks) {
            freq[task - 'A']++;
        }
        
        priority_queue pq;
        for (int f : freq) {
            if (f > 0) pq.push(f);
        }
        
        int time = 0;
        while (!pq.empty()) {
            vector temp;
            int i = 0;
            
            while (i <= n && !pq.empty()) {
                int count = pq.top(); pq.pop();
                if (count > 1) temp.push_back(count - 1);
                time++;
                i++;
            }
            
            for (int count : temp) pq.push(count);
            if (!pq.empty() && i <= n) time += (n - i + 1);
        }
        
        return time;
    }
};

JavaScript Solution

/**
 * @param {character[]} tasks
 * @param {number} n
 * @return {number}
 */
var leastInterval = function(tasks, n) {
    // Count frequency of each task
    const freq = new Array(26).fill(0);
    for (const task of tasks) {
        freq[task.charCodeAt(0) - 'A'.charCodeAt(0)]++;
    }
    
    // Find maximum frequency
    const maxFreq = Math.max(...freq);
    
    // Count tasks with maximum frequency
    const maxFreqTasks = freq.filter(f => f === maxFreq).length;
    
    // Calculate minimum intervals needed
    const minIntervals = (maxFreq - 1) * (n + 1) + maxFreqTasks;
    
    return Math.max(minIntervals, tasks.length);
};

Alternative Solution using Map:

var leastInterval = function(tasks, n) {
    const freq = new Map();
    for (const task of tasks) {
        freq.set(task, (freq.get(task) || 0) + 1);
    }
    
    const maxFreq = Math.max(...freq.values());
    const maxFreqTasks = Array.from(freq.values()).filter(f => f === maxFreq).length;
    
    return Math.max((maxFreq - 1) * (n + 1) + maxFreqTasks, tasks.length);
};

Performance Considerations:

  • Array-based solution is more memory efficient than Map-based solution
  • For small n, the simple formula approach is faster than simulation
  • Priority Queue solution is useful when you need to handle dynamic task scheduling

C# Solution

public class Solution {
    public int LeastInterval(char[] tasks, int n) {
        int[] freq = new int[26];
        foreach (char task in tasks) {
            freq[task - 'A']++;
        }
        
        int maxFreq = freq.Max();
        int maxCount = freq.Count(f => f == maxFreq);
        
        return Math.Max(tasks.Length, (maxFreq - 1) * (n + 1) + maxCount);
    }
}

Alternative Solution using PriorityQueue:

public class Solution {
    public int LeastInterval(char[] tasks, int n) {
        int[] freq = new int[26];
        foreach (char task in tasks) {
            freq[task - 'A']++;
        }
        
        var pq = new PriorityQueue();
        foreach (int f in freq) {
            if (f > 0) pq.Enqueue(f, -f); // Use negative for max heap
        }
        
        int time = 0;
        while (pq.Count > 0) {
            var temp = new List();
            int i = 0;
            
            while (i <= n && pq.Count > 0) {
                int count = pq.Dequeue();
                if (count > 1) temp.Add(count - 1);
                time++;
                i++;
            }
            
            foreach (int count in temp) {
                pq.Enqueue(count, -count);
            }
            
            if (pq.Count > 0 && i <= n) time += (n - i + 1);
        }
        
        return time;
    }
}

Implementation Notes:

  • First solution uses LINQ for cleaner code
  • PriorityQueue solution available in .NET 6+ for optimal performance
  • Both solutions have O(n) time complexity
  • PriorityQueue solution uses more memory but simulates actual scheduling