Single-Threaded CPU

MediumHeap · Simulation🧩 Heap & Top-KLeetCode #1834 ↗Updated

Problem

Task i is [enqueueTime, processingTime]. A single CPU runs one task at a time to completion. Whenever it is free, it picks, among tasks that have already arrived, the one with the shortest processing time (ties → smaller index); if nothing has arrived it idles until something does. Return the order in which task indices are processed.
Input[[1,2],[2,4],[3,2],[4,1]]Output[0,2,3,1]
Input[[7,10],[7,12],[7,5],[7,4],[7,2]]Output[4,3,2,0,1]

1 ≤ n ≤ 105  ·  1 ≤ enqueueTime, processingTime ≤ 109

Try it yourself

Java
class Solution {
    public int[] getOrder(int[][] tasks) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Two orderings are at play: tasks become available by enqueue time (sort once) and are chosen by (processing time, index) (min-heap). Sweep the sorted list into the heap as the clock advances; when the heap is empty, jump the clock to the next arrival.
PatternHeap & Top-K

Instinct "K largest / smallest / closest / most frequent", or "always take the best available next"? Keep a heap - size k for top-K, or a ready-queue for scheduling.

Memory hack Guard the top-K club with a bouncer - a min-heap of size k whose root is the weakest member; anyone stronger kicks them out.

Open the Heap & Top-K guide →

Approaches

Brute ForceRescan All Tasks per Pick

Time O(n2)Space O(n)

Simulate directly. Before each pick, move the clock forward to the earliest pending arrival if the CPU would otherwise idle. Then scan every pending task and take the arrived one with the smallest processing time — scanning indices in ascending order with a strict < resolves ties by index.

Java
public int[] getOrder(int[][] tasks) {
    int n = tasks.length;
    boolean[] done = new boolean[n];
    int[] order = new int[n];
    long time = 0; // can exceed int range
    for (int k = 0; k < n; k++) {
        long earliest = Long.MAX_VALUE;
        for (int i = 0; i < n; i++) if (!done[i]) earliest = Math.min(earliest, tasks[i][0]);
        time = Math.max(time, earliest); // idle until something arrives
        int pick = -1;
        for (int i = 0; i < n; i++) {
            if (!done[i] && tasks[i][0] <= time
                    && (pick == -1 || tasks[i][1] < tasks[pick][1])) pick = i;
        }
        done[pick] = true;
        order[k] = pick;
        time += tasks[pick][1];
    }
    return order;
}

Obviously correct, but 105 tasks means ~1010 steps.

At a glance

LevelApproachTimeSpace
Brute ForceRescan All Tasks per PickO(n2)O(n)
OptimalSort by Arrival + Min-HeapO(n log n)O(n)
Common pitfalls
  • Keeping the clock in an int — 105 tasks × 109 overflows.
  • Advancing time by 1 when idle instead of jumping to the next arrival — TLE.
  • Sorting by processing time up front — ignores which tasks have actually arrived.
Interview tips
  • Name the two keys: availability (sorted list) vs priority (heap).
  • Walk through the idle case explicitly — it is where most bugs hide.
  • Note this is Shortest-Job-First scheduling; mention Task Scheduler / meeting-room variants.
Pattern
Sort + heap sweep → events arrive over time and you repeatedly pick the best available one.
My notes saved in this browser