Greedy Algorithms
Greedy algorithms are a powerful problem-solving strategy that make the locally optimal choice at each step with the hope of finding a globally optimal solution. They work by building up a solution piece by piece, always choosing the next piece that offers the most immediate benefit.
Real-World Analogy
Imagine you’re a hiker trying to reach the highest peak in a mountain range. A greedy approach would be to always take the steepest path upward from your current position, never looking back or considering if a different route might lead to a higher peak later. This works perfectly when the terrain has no local maxima (false peaks), but can fail if there are valleys or plateaus that require temporary descent to reach the true highest point.
Visual Explanation
Let’s visualize how greedy algorithms work using the classic Activity Selection problem:
graph TD
subgraph Activities [Activities with Start/End Times]
A1["A: 1-4"]
A2["B: 3-5"]
A3["C: 0-6"]
A4["D: 5-7"]
A5["E: 8-9"]
A6["F: 5-9"]
end
subgraph Greedy_Process [Greedy Selection Process]
S1["Sort by end time"]
S2["Select A (1-4)"]
S3["Skip B (3-5) - overlaps"]
S4["Skip C (0-6) - overlaps"]
S5["Select D (5-7)"]
S6["Skip F (5-9) - overlaps"]
S7["Select E (8-9)"]
end
subgraph Result [Selected Activities]
R1["A: 1-4"]
R2["D: 5-7"]
R3["E: 8-9"]
end
A1 --> S1
A2 --> S1
A3 --> S1
A4 --> S1
A5 --> S1
A6 --> S1
S1 --> S2
S2 --> S3
S3 --> S4
S4 --> S5
S5 --> S6
S6 --> S7
S2 --> R1
S5 --> R2
S7 --> R3
style R1 fill:#4ade80,stroke:#16a34a
style R2 fill:#4ade80,stroke:#16a34a
style R3 fill:#4ade80,stroke:#16a34a
Explanation: The greedy algorithm sorts activities by their end time and always picks the next activity that doesn’t conflict with the previously selected one. This leads to the optimal solution of 3 non-overlapping activities.
When to Use This Pattern
Use greedy algorithms when you see these characteristics:
- Optimization problem with multiple choices at each step
- Irrevocable decisions - once you make a choice, you can’t go back
- Local optimality seems to lead to global optimality
- No future dependencies - current choice doesn’t affect future options
- Sorting helps - there’s a natural ordering that makes greedy choices meaningful
Complexity Analysis
| Operation | Time Complexity | Space Complexity | Explanation |
|---|---|---|---|
| Greedy Selection | O(N log N) | O(1) | Sorting dominates time complexity; selection is linear |
| Optimal Substructure | O(N) | O(1) | If no sorting needed, linear scan suffices |
| Proof Verification | O(N) | O(1) | Checking greedy choice property |
Derivation:
- Time: Most greedy algorithms require sorting the input, which takes. The actual greedy selection process is typicallyO(N log N)linear scan.O(N)
- Space: Greedy algorithms usually only need constant extra spaceto track the current best choice.O(1)
Common Mistakes
- Assuming greedy works without proof - Not all optimization problems have the greedy choice property
- Wrong sorting criteria - Choosing the wrong metric to sort by can lead to suboptimal solutions
- Not handling edge cases - Empty inputs, single elements, or boundary conditions
- Overlooking dependencies - Some problems have hidden dependencies that break the greedy property
Next Steps
Now that you understand the greedy algorithm concept, let’s move on to practical implementation. Check out the Code Templates page to see standardized implementations of common greedy patterns, or dive into the Practice Problems to apply these concepts to real coding challenges.