Job scheduling

Dec 7, 2025
Updated 1 day ago
6 min read

Job Scheduling — Why Greed Actually Wins Here (And When It Doesn't)

Most articles give you the sorted table and the answer. This one explains why sorting by profit is the right move — not just that it is.


Here's a question nobody asks in class: why does picking the most profitable job first actually work?

Greedy algorithms have this reputation of being "obviously correct" — and that reputation makes students stop thinking. You sort, you pick, you move on. But greedy algorithms fail constantly on problems that look identical to this one. The Fractional Knapsack works greedily. The 0/1 Knapsack doesn't. Both involve picking items with values and constraints.

So what's special about job scheduling? Why does greed give the optimal answer here, and not just a good approximation?

That's what this note is actually about.


The Problem

You have m jobs: .

Each job has:

  • A deadline — the job must be completed at or before this time slot

  • A profit — earned only if the job is completed within its deadline

Assumptions:

  • Each job takes exactly 1 time unit

  • Only one job can run per time slot

  • A job either completes fully (earning full profit) or is skipped (earning nothing)

Objective: Schedule a subset of jobs to maximize total profit, subject to all deadline constraints being met.


The Example

Job

Deadline

Profit

J1

1

150

J2

2

200

J3

1

120

J5

2

90

J4

3

60

Maximum deadline = 3, so we have 3 time slots: [1], [2], [3].

We can schedule at most 3 jobs total, but deadline constraints will tighten this further.


Why Greedy Works Here — The Proof Sketch

Before we run the algorithm, let's understand why it's correct.

Greedy Choice Property: Suppose an optimal schedule exists that does not include the highest-profit job . We claim we can always swap in without reducing profit.

  • has some deadline

  • If any slot is free in the optimal schedule, we add there — profit goes up

  • If all slots are filled, we find the job in those slots with the lowest profit. Since is the highest-profit unscheduled job, . Swap with — profit doesn't decrease

In both cases, including never makes things worse. So any optimal solution can be transformed to include the greedy choice — which means the greedy choice is safe.

This is called the exchange argument — it's the standard proof technique for greedy correctness. Once you've seen it here, you'll recognize it in Huffman coding, activity selection, and MST proofs too.


The Algorithm

plaintext
JobScheduling(jobs):
    Sort jobs in decreasing order of profit
    Initialize slots[1..max_deadline] = empty
    result = []

    for each job J in sorted order:
        for t = J.deadline down to 1:
            if slots[t] is empty:
                slots[t] = J
                result.add(J)
                break

    return result

Key detail: we try to place each job as late as possible within its deadline. This is called the latest-slot-first strategy, and it's deliberate — placing a job early wastes a slot that an earlier-deadline job might desperately need.


Full Trace

Step 1: Sort by profit descending.

Job

Deadline

Profit

J2

2

200

J1

1

150

J3

1

120

J5

2

90

J4

3

60

Slots available: [1] [ ] , [2] [ ] , [3] [ ]


Process J2 (deadline 2, profit 200):

  • Try slot 2 → free → assign J2 to slot 2

Slots: [1] [ ] , [2] [J2] , [3] [ ]


Process J1 (deadline 1, profit 150):

  • Try slot 1 → free → assign J1 to slot 1

Slots: [1] [J1] , [2] [J2] , [3] [ ]


Process J3 (deadline 1, profit 120):

  • Try slot 1 → occupied by J1

  • No earlier slots available → J3 skipped


Process J5 (deadline 2, profit 90):

  • Try slot 2 → occupied by J2

  • Try slot 1 → occupied by J1

  • No slots available → J5 skipped


Process J4 (deadline 3, profit 60):

  • Try slot 3 → free → assign J4 to slot 3

Slots: [1] [J1] , [2] [J2] , [3] [J4]


Final Schedule:

Time Slot

Job

Profit

1

J1

150

2

J2

200

3

J4

60

Jobs scheduled: {J1, J2, J4} — J3 and J5 are dropped.


Why J3 and J5 Are Dropped (Intuition Check)

J3 has deadline 1 — it must run in slot 1. But J1 also has deadline 1 and higher profit. Both can't fit, so J3 goes.

J5 has deadline 2 — it can run in slot 1 or 2. Both are taken by higher-profit jobs. So J5 goes too.

Notice: we didn't arbitrarily skip them. The algorithm tried to fit them — it just couldn't find a valid slot. That's the algorithm being honest about constraints, not greedy being sloppy.


Complexity Analysis

Complexity

Sorting

Slot assignment (naive)

Slot assignment (with Union-Find)

Space

The naive slot assignment loops over deadlines for each job — in the worst case. For large inputs, you can replace it with a Disjoint Set Union (DSU) structure that finds the latest free slot in near amortized — bringing the total to .

For exam purposes, the naive version is expected. For competitive programming, DSU is the move.


Greedy vs. DP — When Does Greedy Fail?

This is worth pausing on.

Job scheduling (unit time, maximize profit) → Greedy works

What if jobs had variable durations? Say J1 takes 3 hours and J2 takes 1 hour, and you have a 4-hour window. Greedy by profit might schedule J1 (3h, profit 200) and skip J2 (1h, profit 150) + J3 (1h, profit 100) — missing a total of 250 for 200.

That's the weighted job scheduling problem → Greedy fails, DP required.

The unit-time assumption is what makes the exchange argument watertight. Once jobs have different lengths, swapping them changes the feasibility of the entire schedule, not just one slot. Greedy loses its guarantee.

Knowing why greedy works also tells you exactly where it breaks.


Quick Self-Test

  • Q1: Why do we assign jobs to the latest available slot rather than the earliest?

  • Q2: In the example, what's the maximum possible profit if we had unlimited time slots?

  • Q3: Would the answer change if J4's deadline was 1 instead of 3?

  • Q4: What property of this problem makes the greedy exchange argument valid?

(Answers: Placing jobs late preserves early slots for jobs that can't go anywhere else. 150+200+120+90+60 = 620 — but deadlines make that impossible. Yes — J4 would compete with J1 and J3 for slot 1, and with profit 60 it would be displaced, reducing total to 350. The unit-time assumption ensures any two jobs can be swapped in the schedule without breaking feasibility elsewhere.)



External References


Part of the DAA Design and Analysis series on NoteHub.