Job Sequencing with Deadlines is a classic greedy scheduling problem. Each job earns a profit but must finish by its own deadline, and you can only run one job per time unit. The trick is realizing that profit-first ordering, combined with placing each job as late as legally possible, is provably optimal.
Problem. You are given n jobs, each with a deadline (the latest time unit by which it must run)
and a profit earned only if the job finishes by that deadline. Each job takes one unit of time and only
one job runs at a time. Schedule a subset of jobs to maximize total profit.
Example: jobs A(d=2, p=100), B(d=1, p=50), C(d=2, p=40), D(d=1, p=30). Best schedule is B at
time 1 and A at time 2 → profit 150. C and D do not fit.
The slow way first
You could try every subset of jobs, check each ordering for deadline feasibility, and keep the best. That is exponential — 2ⁿ subsets — and hopeless beyond a handful of jobs.
The question to ask: if I want the most profit, which job should I never give up? The most profitable one. So sort by profit, take the richest job first, and only fall back when there is physically no room for it.
The idea: richest first, latest slot
Sort jobs by profit descending. Keep an array of time slots 1 … maxDeadline. For each job, scan backward from its deadline looking for the latest empty slot. If you find one, place the job there and bank its profit. If every slot up to its deadline is full, skip the job.
Why the latest free slot rather than the earliest? Filling late leaves the early slots open for jobs with tight (small) deadlines that have nowhere else to go. That is what makes the greedy choice safe.
Walk through it
Step through the animation. Jobs are sorted A:100, B:50, C:40, D:30. A takes slot 2 (its deadline). B takes slot 1. C wants a slot ≤ 2 but both are full, so it is dropped; D wants slot 1, also full, so it is dropped too. Final profit: 150.
Pseudocode
sort jobs by profit, descending
slot[1 .. maxDeadline] = all empty
profit = 0
for each job (richest first):
t = job.deadline
while t >= 1 and slot[t] is filled:
t = t - 1 # walk to an earlier slot
if t >= 1: # found a legal empty slot
slot[t] = job.id
profit = profit + job.profit
# else: no room, skip this job
return profit, slotThe Python solution
def job_sequencing(jobs):
jobs.sort(key=lambda j: j.profit, reverse=True)
slot = [None] * max(j.deadline for j in jobs)
profit = 0
for job in jobs:
t = job.deadline - 1
while t >= 0 and slot[t] is not None:
t -= 1
if t >= 0:
slot[t] = job.id
profit += job.profit
return profit, slot- We sort by
profitin reverse so the most valuable job is considered first. slotis zero-indexed, so deadlinedmaps to indexd - 1; we walk back witht -= 1.- The
whileloop finds the latest empty slot at or before the deadline. - Lines 9-11 are the commit: if a legal empty slot exists we place the job and add its profit.
- If
tfalls below 0 the job had no room, and we simply move on to the next one.
Complexity
| Case | Time | Notes |
|---|---|---|
| Brute force (all subsets) | O(2ⁿ · n) (moderate) | every subset, checked |
| Greedy + linear slot scan | O(n log n + n·d) (moderate) | sort, then scan slots |
| Greedy + union-find slots | O(n log n · α) (moderate) | find free slot in near-O(1) |
O(d) (moderate)The sort dominates at O(n log n); the slot scan adds O(n·d) in the simple version. A union-find that points each slot to the next free one earlier collapses the scan to near-constant time.
When this pattern shows up
Whenever a scheduling problem says "maximize profit / value, one task at a time, each with a deadline," reach for sort-by-value-descending plus latest-feasible-slot. The same exchange-argument greedy powers many interval and deadline problems.
Do not place a job in the earliest free slot — that wastes a scarce early slot a tight-deadline job might need. Always walk backward from the deadline to the latest free slot.
Practice
Jobs A(d=2,p=100), B(d=1,p=50), C(d=2,p=40). After placing A and B, where can C go?
1. In what order are jobs considered?
2. Why place each job in the latest free slot at or before its deadline?
3. What happens to a job when no empty slot exists at or before its deadline?
4. What dominates the running time of the greedy solution?