Task Scheduler: Minimum Time

Problem

Each number in the array is a task type. One task takes one time unit, and the CPU can also be idle for a unit. Two tasks of the same type must have at least K time units between them (K units of other tasks or idle time). Tasks can be done in any order. Print the smallest total time to finish all tasks. Input: the number of tasks, the types, then K.

Constraints

  • 1 <= n <= 10^4
  • 0 <= K <= 100

Examples

Input

6
1 1 1 2 2 2
2

Output

8

Solutions

Best approachTime O(n)Space O(types)

Place the most frequent type first, with K gaps between its copies. This makes (maxCount - 1) rows of size K + 1 and a last row. Other tasks fill the gaps, so idle time appears only when there are too few of them.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Least time.
 * Input   : Types and K.
 * Output  : The time.
 * Approach: Formula from the most frequent type
 * Time    : O(n)
 * Space   : O(types)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static long solve(int[] a, int k) {
        // Step 1: Count each type. The most frequent type decides the shape of the schedule.
        java.util.Map<Integer, Integer> freq = new java.util.HashMap<Integer, Integer>();
        int maxCount = 0;
        for (int type : a) {
            int now = freq.merge(type, 1, Integer::sum);
            maxCount = Math.max(maxCount, now);
        }
        // Step 2: How many types have that same highest count? They all end the last row.
        int withMax = 0;
        for (int count : freq.values()) {
            if (count == maxCount) {
                withMax++;
            }
        }
        // Step 3: Make full rows of size K + 1, then a last row with the top types.
        // Idle time is only needed when the rows are not full.
        // Step 4: If other tasks fill every gap, the time is just the number of tasks.
        return Math.max(a.length, (long) (maxCount - 1) * (k + 1) + withMax);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int size = scanner.nextInt();
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = scanner.nextInt();
        }
        int k = scanner.nextInt();
        System.out.println(solve(a, k));
    }
}
Hints (2)
  1. Why can other tasks fill the gaps without breaking the rule?
  2. When is the answer just the number of tasks?