Greedy Fundamentals & Intervals
Work through examples, try the reasoning yourself, then put it into practice.
View SlidesBefore you start
- Sort records by a field and trace min-heap insertion/removal.
What you will practice
- Use an exchange argument to justify earliest-finish scheduling under half-open endpoints.
- Reconstruct current-piece merge costs and diagnose a greedy rule after its objective changes.
In this lesson
Lesson
5 min readGreedy Fundamentals & Intervals
Two exercises ask for an optimum without enumerating all possibilities:
MaxNonOverlapping(intervals) maximizes a count, and OptimalMergeCost(sizes)
minimizes repeated merge work. You need sorting and a min-heap. The central skill
is identifying what can be exchanged in an optimum without worsening it.
Schedule by the resource you leave available
Intervals are half-open, with Start < End. [1,3) and [3,5) are
compatible. Sort by increasing end time and keep an interval when its start is
at least the last selected end. Negative endpoints are valid: initializing the
last end to 0 would wrongly reject an interval ending before 0. Use an explicit
“nothing chosen yet” state or a suitable lower bound.
Work through [0,8), [1,3), [2,4), [3,5), [5,7):
| In finish order | Last selected end before | Decision |
|---|---|---|
[1,3) |
none | Take; last end becomes 3 |
[2,4) |
3 | Skip; 2 < 3 |
[3,5) |
3 | Take; touching is allowed |
[5,7) |
5 | Take |
[0,8) |
7 | Skip |
The answer is 3. Sorting by earliest start takes [0,8) and yields only one.
Choosing the shortest duration is also unsafe: with [0,3), [2,4), [3,6),
taking shortest [2,4) blocks both other intervals, while they form a pair.
Prove the first choice, then reuse the proof
Let G be the earliest-finishing interval and let O be the first interval of an
optimal schedule. Since G.End <= O.End, replacing O by G leaves every later
interval compatible: their starts were at least O.End and thus at least G.End.
The replacement preserves the number selected. An optimum therefore exists
that begins with G. Remove G and every incompatible interval, and apply the
same argument to the remaining problem.
This proof uses equal value per selected interval. If intervals carry
profits, earliest finish can lose: [0,2) worth 2 and [2,4) worth 2 lose to
[0,4) worth 10. That is a different optimization problem, commonly solved
with a predecessor lookup and dynamic programming. A greedy slogan does not
transfer automatically when the objective changes.
Sorting dominates at O(n log n); the scan is O(n). The reference copies the input before sorting. The statement requires the optimal count; it does not require returning a particular optimal schedule.
Merge costs are repeated participation
A merge of sizes a and b costs a+b and replaces them with a+b. The total is
not just the final size: a byte participates again whenever its merged file is
merged later. In a merge tree, a file of size w at depth d contributes w*d.
This exposes the exchange argument: if a larger weight is deeper than a smaller
one, swapping them cannot increase the cost. Some optimum places the two
smallest weights at a deepest sibling pair. Contract that pair into their sum;
solving the smaller problem optimally gives the greedy recurrence.
For [1,2,7,8], use a min-heap of current pieces:
| Pop two | Cost added | Remaining pieces | Total |
|---|---|---|---|
| 1, 2 | 3 | [3,7,8] |
3 |
| 3, 7 | 10 | [8,10] |
13 |
| 8, 10 | 18 | [18] |
31 |
Choosing 7 and 8 first, then 1 and 2, costs 15+3+18=36. Sorting the original
sizes once and pairing consecutive values is not enough: the new size 3 must
compete with the still-unmerged originals. Reinsert every merged size.
Empty or singleton inputs cost 0; zero-sized files are legal. There are n-1
merges for n>0, and heap operations make total time O(n log n) with O(n) space.
Accumulate total cost in int64 in Go; intermediate merged sizes also need to
fit the representation, rather than narrowing after the sum has overflowed.
Complete, diagnose, transfer
- For
[-5,-2), [-3,0), [-2,1), [1,2), the first chosen interval ends at -2. Finish the scan and give the count. What happens if compatibility uses>? - For sizes
[2,2,3,9], the first merge costs 4. Complete the heap history and total. Explain why the next merge uses an original 3 and a newly created 4. - Change the scheduling model to closed nonempty intervals. Which single comparison changes, and which part of the proof is retained?
Check your reconstruction
- Skip
[-3,0), take[-2,1)and[1,2): count 3. Using>rejects touching intervals and changes the answer for this half-open contract. - Remaining
[3,4,9]; merge 3+4=7, then 7+9=16. Total4+7+16=27. - Compatibility becomes
next.Start > last.End; the earliest-finish exchange still leaves at least as much room for all later compatible intervals.
Implement both exercises, then compare small cases against exhaustive schedule subsets and all possible pairwise merge choices. For a later independent check, construct your own failure of “largest merge first” and explain the repeated cost using leaf depth rather than only reporting a number.
Practice sequence
Use the order below for a guided path, or choose an item to revisit. A pass records a successful attempt; try a fresh example later to check what you can reconstruct.
- Step 1
Interval Scheduling Max
- Step 2
Optimal Merge Cost
- Step 3
Greedy & Intervals Checkpoint
Trace fresh cases, diagnose a failed invariant, then revisit the linked explanation and implementation.