Greedy Algo

Problems Article MCQs

Greedy Algorithms โ€” Complete Step-by-Step Guide

Module 15 โ€” Greedy Algorithms: Making the locally best choice at every step Structured as Topic โ†’ Plain-English Explanation โ†’ Real Code โ†’ Visual Diagram โ†’ Complexity โ†’ Common Pitfalls.


1. The Greedy Approach & The Greedy-Choice Property

A greedy algorithm constructs a solution piece by piece, always making the choice that offers the most immediate, local benefit at that exact moment โ€” without ever looking backward or reconsidering past decisions.

Unlike Dynamic Programming, which exhaustively evaluates multiple overlapping decisions, a greedy algorithm makes one irreversible choice per step. It yields an optimal solution if and only if the problem exhibits two mathematical properties:

  1. Greedy-Choice Property: A globally optimal solution can always be reached by making locally optimal (greedy) choices.
  2. Optimal Substructure: An optimal solution to the overall problem contains optimal solutions to its subproblems.
Analogy: Making change with the fewest coins by always grabbing the largest coin denomination that fits is greedy. It works perfectly for standard US/Indian currency (e.g., 25ยข, 10ยข, 5ยข, 1ยข), but fails for non-canonical denominations like {1, 3, 4} when making change for 6: greedy picks 4 + 1 + 1 (3 coins), whereas the true optimum is 3 + 3 (2 coins).

2. Activity Selection / Interval Scheduling

Given $n$ activities with start time $s[i]$ and finish time $f[i]$, select the maximum number of mutually compatible (non-overlapping) activities that a single person or machine can perform.

The Greedy Rule: Sort by Finish Time

Always pick the activity that finishes earliest, because it leaves the maximum remaining time available for all subsequent activities.

struct Activity {
    int start, finish, id;
};

bool compareFinish(const Activity& a, const Activity& b) {
    return a.finish < b.finish;
}

vector<Activity> selectActivities(vector<Activity>& acts) {
    sort(acts.begin(), acts.end(), compareFinish);
    vector<Activity> selected;

    int lastFinishTime = -1;
    for (const auto& a : acts) {
        if (a.start >= lastFinishTime) {
            selected.push_back(a);
            lastFinishTime = a.finish;
        }
    }
    return selected;
}
024 6810 121416 A1 [1, 4] ✓ A2 [3, 5] ✗ A3 [5, 7] ✓ A4 [8, 12] ✓ A5 [10, 15] ✗ A6 [13, 16] ✓
Figure 15.1 โ€” Activity Selection: Greedily picking activities that finish earliest leaves maximum room for future events

3. Fractional Knapsack vs 0/1 Knapsack

  • Fractional Knapsack: Items are continuous (like flour, gold dust, or oil). You can take any fraction $ rac{w}{W}$ of an item. Greedy works 100%: Sort items by their value-to-weight ratio ($val[i] / wt[i]$) in descending order and greedily take as much of the densest item as capacity allows. Time Complexity: $O(n log n)$ due to sorting.
  • 0/1 Knapsack: Items are indivisible (take all or nothing). Greedy fails! Dynamic Programming ($O(n cdot W)$) is strictly required because taking the highest-density item might leave wasted space that prevents a better combination.
Knapsack Capacity: 50 kg Item A: 10kg ($60) • Ratio: $6/kg Item B: 20kg ($100) • Ratio: $5/kg Item C: 20kg of 30kg ($80) • Ratio: $4/kg Greedy Density Sorting: • Item A: 10kg, $60 → $6.0 / kg (Take 100%) • Item B: 20kg, $100 → $5.0 / kg (Take 100%) • Item C: 30kg, $120 → $4.0 / kg (Take 20kg fraction) Total Value Achieved: $240 (Globally Optimal)
Figure 15.2 โ€” Fractional Knapsack: Greedy value-to-weight ratio ordering guarantees the maximum possible total value

4. Classic Greedy Problems Matrix & Proof Methods

Problem Greedy Decision Rule Time Complexity Notes
Activity Selection Earliest finish time first $O(n log n)$ Proved via Exchange Argument
Fractional Knapsack Highest value/weight ratio first $O(n log n)$ Continuous optimization
Huffman Coding Merge two lowest frequency trees $O(n log n)$ Optimal prefix-free code
Kruskal's MST Add cheapest edge without creating cycles $O(E log E)$ Uses Disjoint Set (Union-Find)
Prim's MST Connect nearest unvisited vertex $O(E log V)$ Uses Priority Queue
Dijkstra's Algorithm Relax edges from closest known vertex $O((V + E) log V)$ Non-negative edge weights only
Common Pitfall: Never assume a problem is greedy without testing a counterexample! For coin change with coins `{1, 3, 4}`, greedy fails on amount 6. For 0/1 Knapsack, greedy fails on items `{(w:3, v:5), (w:2, v:3), (w:2, v:3)}` with capacity 4. When in doubt, check if an exchange argument holds.
Practice Greedy Algo MCQs
Master Greedy Algo concepts with timed, competitive MCQs with detailed explanations.
Start Topic Quiz →
Yukti Mascot