Skip to content

Commit d5acaa8

Browse files
authored
Update greedy_algorithms.md
1 parent b1b83b3 commit d5acaa8

File tree

1 file changed

+95
-102
lines changed

1 file changed

+95
-102
lines changed

notes/greedy_algorithms.md

Lines changed: 95 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,150 @@
1-
## Greedy Algorithms
1+
## Greedy algorithms
22

3-
Greedy methods construct a solution piece by piece, always choosing the currently best-looking option according to a simple rule. The subtlety is not the rule itself but the proof that local optimality extends to global optimality. Two proof tools do most of the work: exchange arguments (you can swap an optimal solution’s first “deviation” back to the greedy choice without harm) and loop invariants (you maintain a statement that pins down exactly what your partial solution guarantees at each step).
4-
5-
Formally, consider a finite ground set $E$, a family of feasible subsets $\mathcal{F}\subseteq 2^E$, and a weight function $w:E\to \mathbb{R}$. A generic greedy scheme orders elements of $E$ by a key $\kappa(e)$ and scans them, adding $e$ to the building solution $S$ if $S\cup\{e\}\in\mathcal{F}$. Correctness means
6-
7-
$$
8-
\text{Greedy}(E,\mathcal{F},w,\kappa)\in\arg\max\{\,w(S):S\in\mathcal{F}\,\}.
9-
$$
10-
11-
The nice, crisp setting where this always works is the theory of matroids. Outside that, correctness must be argued problem-by-problem.
3+
Greedy algorithms build a solution one step at a time. At each step, grab the option that looks best *right now* by some simple rule (highest value, earliest finish, shortest length, etc.). Keep it if it doesn’t break the rules of the problem.
124

135
```
14-
scan order: e1 e2 e3 e4 e5 ...
15-
feasible? Y N Y Y N
16-
solution S: {e1, e3, e4}
6+
1) Sort by your rule (the “key”).
7+
2) Scan items in that order.
8+
3) If adding this item keeps the partial answer valid, keep it.
9+
4) Otherwise skip it.
1710
```
1811

19-
### The greedy-choice principle and exchange arguments
20-
21-
Greedy methods feel simple on the surface—always take the best-looking move right now—but the proof that this is globally safe is subtle. The core idea is to show that at the first moment an optimal solution “disagrees” with your greedy choice, you can surgically swap in the greedy move without making things worse. Do that repeatedly and you literally transform some optimal solution into the greedy one. That’s the exchange argument.
22-
23-
Let $E$ be a finite ground set of “atoms.” Feasible solutions are subsets $S\subseteq E$ belonging to a family $\mathcal{F}\subseteq 2^E$. The objective is additive:
24-
25-
$$
26-
\text{maximize } w(S)=\sum_{e\in S} w(e)\quad\text{subject to } S\in\mathcal{F},\qquad w:E\to\mathbb{R}.
27-
$$
12+
Picking the best “now” doesn’t obviously give the best “overall.” The real work is showing that these local choices still lead to a globally best answer.
2813

29-
A generic greedy algorithm fixes an order $e_1,e_2,\dots,e_m$ determined by a key $\kappa$ (for example, sort by nonincreasing $w$ or by earliest finishing time), then scans the elements and keeps $e_i$ whenever $S\cup\{e_i\}\in\mathcal{F}$.
14+
**Two proof tricks you’ll see a lot:**
3015

31-
Two structural properties make the exchange proof go through.
16+
* *Exchange argument.* Take any optimal solution that disagrees with greedy at the first point. Show you can “swap in” the greedy choice there without making the solution worse or breaking feasibility. Do this repeatedly and you morph some optimal solution into the greedy one—so greedy must be optimal.
17+
* *Loop invariant.* Write down a sentence that’s true after every step of the scan (e.g., “the current set is feasible and as good as any other set built from the items we’ve seen”). Prove it stays true as you process the next item; at the end, that sentence implies optimality.
3218

33-
1. Feasibility exchange. Whenever $A,B\in\mathcal{F}$ with $|A|<|B|$, there exists $x\in B\setminus A$ such that $A\cup\{x\}\in\mathcal{F}$. This “augmentation flavor” is what lets you replace a non-greedy element by a greedy one while staying feasible.
19+
*Picture it like this:*
3420

35-
2. Local dominance. At the first position where greedy would keep $g$ but some optimal $O$ keeps $o\neq g$, you can drop some element $x\in O\setminus A$ and insert $g$ so that
21+
```
22+
position → 1 2 3 4 5
23+
greedy: [✓] [✗] [✓] [✓] [✗]
24+
some optimal:
25+
✓ ✓ ✗ ? ?
26+
First mismatch at 3 → swap in greedy’s pick without harm.
27+
Repeat until both rows match → greedy is optimal.
28+
```
3629

37-
$$
38-
A\cup\{g\}\cup\bigl(O\setminus\{x\}\bigr)\in\mathcal{F}
39-
\quad\text{and}\quad
40-
w(g)\ge w(x),
41-
$$
30+
**Where greedy shines automatically: matroids (nice constraint systems).**
31+
There’s a tidy setting where greedy is *always* right (for nonnegative weights): when your “what’s allowed” rules form a **matroid**. You don’t need the symbols—just the vibe:
4232

43-
where $A$ is the common prefix chosen by both up to that point. The inequality ensures the objective does not decrease during the swap.
33+
1. **You can start from empty.**
34+
2. **Throwing things out never hurts.** If a set is allowed, any subset is allowed.
35+
3. **Smooth growth (augmentation).** If one allowed set is smaller than another, you can always add *something* from the bigger one to the smaller and stay allowed.
4436

45-
When $(E,\mathcal{F})$ is a matroid, the feasibility exchange always holds; if you also order by nonincreasing $w$, local dominance holds trivially with $x$ chosen by the matroid’s augmentation. Many everyday problems satisfy these two properties even without full matroid machinery.
37+
That third rule prevents dead ends and is exactly what exchange arguments rely on. In matroids, the simple “sort by weight and take what fits” greedy is guaranteed optimal. Outside matroids, greedy can still work—but you must justify it for the specific problem using exchange/invariants.
4638

47-
Write the greedy picks as a sequence $G=(g_1,g_2,\dots,g_k)$, in the order chosen. The following lemma is the workhorse.
4839

49-
**Lemma (first-difference exchange).** Suppose there exists an optimal solution $O$ whose first $t-1$ elements agree with greedy, meaning $g_1,\dots,g_{t-1}\in O$. If $g_t\in O$ as well, continue. Otherwise there exists $x\in O\setminus\{g_1,\dots,g_{t-1}\}$ such that
40+
### Reachability on a line
5041

51-
$$
52-
O' \;=\;\bigl(O\setminus\{x\}\bigr)\cup\{g_t\}\in\mathcal{F}
53-
\quad\text{and}\quad
54-
w(O')\ge w(O).
55-
$$
42+
- You stand at square \$0\$ on squares \$0,1,\dots,n-1\$.
43+
- Each square \$i\$ has a jump power \$a\[i]\$. From \$i\$ you may land on any of \$i+1, i+2, \dots, i+a\[i]\$.
44+
- Goal: decide if you can reach \$n-1\$; if not, report the furthest reachable square.
5645

57-
Hence there is an optimal solution that agrees with greedy on the first $t$ positions.
46+
Example
5847

59-
*Proof sketch.* Let $A_{t-1}=\{g_1,\dots,g_{t-1}\}$. Because greedy considered $g_t$ before any element in $O\setminus A_{t-1}$ that it skipped, local dominance says some $x\in O\setminus A_{t-1}$ can be traded for $g_t$ without breaking feasibility and without decreasing weight. This creates $O'$ optimal and consistent with greedy for one more step. Apply the same reasoning inductively.
48+
* Input: \$a=\[3,1,0,0,4,1]\$, so \$n=6\$ (squares \$0..5\$).
6049

61-
Induction on $t$ yields the main theorem: there exists an optimal solution that agrees with greedy everywhere, hence greedy is optimal.
50+
```
51+
indices: 0 1 2 3 4 5
52+
a[i] : 3 1 0 0 4 1
53+
reach : ^ start at 0
54+
```
6255

63-
It helps to picture the two solutions aligned in the greedy order. The top row is the greedy decision at each position; the bottom row is some optimal solution, possibly disagreeing. At the first disagreement, one swap pushes the optimal line upward to match greedy, and the objective value does not drop.
56+
From any \$i\$, the allowed landings are a range:
6457

6558
```
66-
positions → 1 2 3 4 5 6 7
67-
greedy G: [g1] [g2] [g3] [g4] [g5] [g6] [g7]
68-
optimal O: [g1] [g2] [ o ] [ ? ] [ ? ] [ ? ] [ ? ]
69-
70-
exchange at position 3:
71-
drop some x from O beyond position 2 and insert g3
72-
73-
after swap:
74-
optimal O': [g1] [g2] [g3] [ ? ] [ ? ] [ ? ] [ ? ]
59+
i=0 (a[0]=3): 1..3
60+
i=1 (a[1]=1): 2
61+
i=2 (a[2]=0): —
62+
i=3 (a[3]=0): —
63+
i=4 (a[4]=4): 5..8 (board ends at 5)
7564
```
7665

77-
The key is not the letter symbols but the invariants. Up to position $t-1$, both solutions coincide. The swap keeps feasibility and weight, so you have a new optimal that also matches at position $t$. Repeat, and the bottom row becomes the top row.
66+
---
7867

79-
### Matroids
68+
Baseline idea (waves)
8069

81-
Greedy methods don’t usually get ironclad guarantees, but there is a beautiful class of feasibility systems where they do. That class is the matroids. Once your constraints form a matroid, the simplest weight-ordered greedy scan is not a heuristic anymore; it is provably optimal for every nonnegative weight assignment.
70+
“Paint everything reachable, one wave at a time.”
8271

83-
A matroid is a pair $(E,\mathcal{I})$ with $E$ a finite ground set and $\mathcal{I}\subseteq 2^E$ the “independent” subsets. Three axioms hold.
72+
1. Start with \${0}\$ reachable.
73+
2. For each already-reachable \$i\$, add all \$i+1..i+a\[i]\$.
74+
3. Stop when nothing new appears.
8475

85-
* Non-emptiness says $\varnothing\in\mathcal{I}$.
86-
* Heredity says independence is downward-closed: if $A\in\mathcal{I}$ and $B\subseteq A$, then $B\in\mathcal{I}$.
87-
* Augmentation says independence grows smoothly: if $A,B\in\mathcal{I}$ with $|A|<|B|$, then some $x\in B\setminus A$ exists with $A\cup\{x\}\in\mathcal{I}$.
76+
Walk on the example:
8877

89-
The last axiom is the heart. It forbids “dead ends” where a smaller feasible set cannot absorb a single element from any larger feasible set. That smoothness is exactly what greedy needs to keep repairing early choices.
78+
```
79+
start: reachable = {0}
80+
from 0: add {1,2,3} → reachable = {0,1,2,3}
81+
from 1: add {2} → no change
82+
from 2: add {} → a[2]=0
83+
from 3: add {} → a[3]=0
84+
stop: no new squares → furthest = 3; last (5) unreachable
85+
```
9086

91-
### Reachability on a line
87+
Correct, but can reprocess many squares.
9288

93-
You’re standing on square 0 of a line of squares $0,1,\dots,n-1$.
94-
Each square $i$ tells you how far you’re allowed to jump forward from there: a number $a[i]$. From $i$, you can jump to any square $i+1, i+2, \dots, i+a[i]$. The goal is to decide whether you can ever reach the last square, and, if not, what the furthest square is that you can reach.
89+
---
9590

96-
**Example inputs and outputs**
91+
One-pass trick (frontier)
9792

98-
Input array: `a = [3, 1, 0, 0, 4, 1]`
99-
There are 6 squares (0 through 5).
100-
Correct output: you cannot reach the last square; the furthest you can get is square `3`.
93+
Carry one number while scanning left→right: the furthest frontier \$F\$ seen so far.
10194

102-
Baseline (slow)
95+
Rules:
10396

104-
Think “paint everything I can reach, one wave at a time.”
97+
* If you are at \$i\$ with \$i>F\$, you hit a gap → stuck forever.
98+
* Otherwise, extend \$F \leftarrow \max(F,\ i+a\[i])\$ and continue.
10599

106-
1. Start with square 0 marked “reachable.”
107-
2. For every square already marked, paint all squares it can jump to.
108-
3. Keep doing this until no new squares get painted.
100+
At the end:
109101

110-
This is correct because you literally try every allowed jump from every spot you know is reachable. It can be wasteful, though, because the same squares get reconsidered over and over in dense cases.
102+
* Can reach last iff \$F \ge n-1\$.
103+
* Furthest reachable square is \$F\$ (capped by \$n-1\$).
111104

112-
Walking the example:
105+
Pseudocode
113106

114107
```
115-
start: reachable = {0}
116-
from 0: can reach {1,2,3} → reachable = {0,1,2,3}
117-
from 1: can reach {2} → no change
118-
from 2: can reach {} → no change (a[2]=0)
119-
from 3: can reach {} → no change (a[3]=0)
120-
done: no new squares → furthest is 3, last is unreachable
108+
F = 0
109+
for i in 0..n-1:
110+
if i > F: break
111+
F = max(F, i + a[i])
112+
113+
can_reach_last = (F >= n-1)
114+
furthest = min(F, n-1)
121115
```
122116

123-
**How it works**
117+
Why this is safe (one line): \$F\$ always equals “best jump end discovered from any truly-reachable square \$\le i\$,” and never decreases; if \$i>F\$, no earlier jump can help because its effect was already folded into \$F\$.
124118

125-
Carry one number as you sweep left to right: `F`, the furthest square you can reach **so far**.
126-
Rule of thumb:
119+
walkthrough on the example
127120

128-
* If you’re looking at square `i` and `i` is beyond `F`, you’re stuck forever.
129-
* Otherwise, extend the frontier with `F = max(F, i + a[i])` and move on.
121+
We draw the frontier as a bracket reaching to \$F\$.
130122

131-
That’s it—one pass, no backtracking.
123+
Step \$i=0\$ (inside frontier since \$0\le F\$); update \$F=\max(0,0+3)=3\$.
124+
125+
```
126+
indices: 0 1 2 3 4 5
127+
[===============F]
128+
0 1 2 3
129+
F=3
130+
```
132131

133-
Why this is safe in a sentence: `F` always summarizes “the best jump end we have discovered from any square we truly reached,” and it never goes backward; if you hit a gap where `i > F`, then no earlier jump can help because its effect was already folded into `F`.
132+
Step \$i=1\$: still \$i\le F\$. Update \$F=\max(3,1+1)=3\$ (no change).
133+
Step \$i=2\$: \$F=\max(3,2+0)=3\$ (no change).
134+
Step \$i=3\$: \$F=\max(3,3+0)=3\$ (no change).
134135

135-
Plugging in the same numbers
136+
Now \$i=4\$ but \$4>F(=3)\$ → gap → stuck.
136137

137138
```
138-
a = [3, 1, 0, 0, 4, 1]
139-
n = 6
140-
F = 0 # we start at square 0 (we’ll extend immediately at i=0)
141-
142-
i=0: 0 ≤ F → F = max(0, 0+3) = 3
143-
i=1: 1 ≤ F → F = max(3, 1+1) = 3
144-
i=2: 2 ≤ F → F = max(3, 2+0) = 3
145-
i=3: 3 ≤ F → F = max(3, 3+0) = 3
146-
i=4: 4 > F → stuck here
139+
indices: 0 1 2 3 4 5
140+
[===============F] x (i=4 is outside)
141+
F=3
147142
```
148143

149-
Final state: `F = 3`, which means the furthest reachable square is 3. Since `F < n-1 = 5`, the last square is not reachable.
144+
Final: \$F=3\$. Since \$F\<n-1=5\$, last is unreachable; furthest reachable square is \$3\$.
150145

151-
Summary
146+
Complexity: time \$O(n)\$, space \$O(1)\$.
152147

153-
* Time: $O(n)$ (single left-to-right pass)
154-
* Space: $O(1)$
155148

156149
### Minimum spanning trees
157150

0 commit comments

Comments
 (0)