630 - Course Schedule III
Difficulty: Hard | Pattern: Greedy + Max-Heap | Company tags: Google, Amazon
Problem Statement
There are n different online courses numbered from 1 to n. You are given an array courses where courses[i] = [durationi, lastDayi] indicates that the ith course should be taken continuously for durationi days and must be finished before or on lastDayi.
You will start on the 1st day. Return the maximum number of courses that you can take.
Example 1:
Input: courses = [[100,200],[200,1300],[1000,1250],[2000,3200]]
Output: 3
Approach: Sort by Deadline + Max-Heap — O(n log n)
Key insight: Sort by deadline. Take each course greedily. If adding a course exceeds its deadline, replace the longest course taken so far (if it's longer) — this frees up time without reducing count.
import heapq
def scheduleCourse(courses: list[list[int]]) -> int:
courses.sort(key=lambda x: x[1]) # sort by deadline
max_heap = [] # stores durations (negated for max-heap)
time = 0
for duration, last_day in courses:
if time + duration <= last_day:
heapq.heappush(max_heap, -duration)
time += duration
elif max_heap and -max_heap[0] > duration:
# Replace longest course with current shorter course
time += duration + max_heap[0] # max_heap[0] is negative
heapq.heapreplace(max_heap, -duration)
return len(max_heap)
Dry Run
courses = [[100,200],[200,1300],[1000,1250],[2000,3200]] (already sorted by deadline)
| course | time | action | heap |
|---|---|---|---|
| [100,200] | 0+100=100 lte 200 | take | [-100] |
| [200,1300] | 100+200=300 lte 1300 | take | [-200,-100] |
| [1000,1250] | 300+1000=1300 gt 1250 | 200 gt 1000? No | [-200,-100] |
| [2000,3200] | 300+2000=2300 lte 3200 | take | [-2000,-200,-100] |
Result: len(heap) = 3 ✓
Why Sort by Deadline?
A course with an earlier deadline must be completed first. Otherwise we might take a long course that prevents us from meeting an earlier deadline for a short course.
Complexity
- Time: O(n log n)
- Space: O(n)