Bird
Raised Fist0
DSA Cprogramming

Why Greedy Works and When It Fails in DSA C - Why This Pattern

Choose your learning style10 modes available
Mental Model
Greedy means making the best choice right now without worrying about the future. It works when these local best choices lead to the best overall solution.
Analogy: Imagine picking coins from a pile to get the most money. If you always pick the biggest coin first, you get the most money quickly. But if some coins are tricky, picking the biggest first might not give the best total.
Coins pile: 25 -> 10 -> 5 -> 1 -> null
Pick biggest coin each time -> total grows fast
But sometimes picking smaller coins first is better
Dry Run Walkthrough
Input: Coins: 25, 10, 5, 1; Amount to make: 30
Goal: Show greedy picks biggest coin first and when it works or fails
Step 1: Pick biggest coin ≤ 30: 25
Picked: 25 -> Remaining amount: 5
Why: Greedy picks biggest coin to reduce amount quickly
Step 2: Pick biggest coin ≤ 5: 5
Picked: 25 -> 5 -> Remaining amount: 0
Why: Greedy finishes with smallest coins to reach exact amount
Step 3: Result: coins picked 25 and 5, total 30
Picked coins: 25 -> 5 -> null
Why: Greedy works here because coins fit amount exactly
Step 4: Change coins to 20, 15, 5, 1; Amount: 30
Coins: 20 -> 15 -> 5 -> 1 -> null
Why: Test when greedy fails
Step 5: Pick biggest coin ≤ 30: 20
Picked: 20 -> Remaining amount: 10
Why: Greedy picks 20 first
Step 6: Pick biggest coin ≤ 10: 5 (twice)
Picked: 20 -> 5 -> 5 -> Remaining amount: 0
Why: Greedy picks 5s since 15 > 10
Step 7: Result: coins picked 20, 5 and 5, total 30
Picked coins: 20 -> 5 -> 5 -> null
Why: Greedy solution uses 3 coins
Step 8: Better solution: pick 15 and 15
Picked coins: 15 -> 15 -> null
Why: Greedy fails because picking two 15s is better but greedy never tries
Result:
Final greedy picks: 20 -> 5 -> 5 -> null (3 coins)
Better picks: 15 -> 15 -> null (2 coins)
Shows greedy can fail if local best choice misses better global solution
Annotated Code
DSA C
#include <stdio.h>

// Function to find minimum coins using greedy
void greedy_coin_change(int coins[], int n, int amount) {
    printf("Coins picked: ");
    for (int i = 0; i < n; i++) {
        while (amount >= coins[i]) {
            amount -= coins[i];
            printf("%d -> ", coins[i]); // pick coin
        }
    }
    printf("null\n");
}

int main() {
    int coins1[] = {25, 10, 5, 1};
    int amount1 = 30;
    printf("Example 1: Coins = 25,10,5,1; Amount = 30\n");
    greedy_coin_change(coins1, 4, amount1);

    int coins2[] = {20, 15, 5, 1};
    int amount2 = 30;
    printf("Example 2: Coins = 20,15,5,1; Amount = 30\n");
    greedy_coin_change(coins2, 4, amount2);

    return 0;
}
while (amount >= coins[i]) {
keep picking current coin while it fits in remaining amount
amount -= coins[i];
reduce amount by picked coin value
printf("%d -> ", coins[i]);
print picked coin to show greedy choice
OutputSuccess
Example 1: Coins = 25,10,5,1; Amount = 30 Coins picked: 25 -> 5 -> null Example 2: Coins = 20,15,5,1; Amount = 30 Coins picked: 20 -> 5 -> 5 -> null
Complexity Analysis
Time: O(n) because we check each coin type once and pick as many as possible
Space: O(1) because we only use fixed extra space for counters and output
vs Alternative: Compared to dynamic programming which tries all combinations with O(n*amount) time, greedy is faster but can fail if coins are not standard
Edge Cases
Amount is zero
No coins are picked, output is empty
DSA C
while (amount >= coins[i]) {
Coins do not include 1 and amount cannot be formed exactly
Greedy picks coins until no coin fits, leftover amount remains unhandled
DSA C
while (amount >= coins[i]) {
Single coin type equal to amount
Greedy picks that coin once
DSA C
while (amount >= coins[i]) {
When to Use This Pattern
When a problem asks for making change or selecting items step-by-step with local best choices, check if greedy works by testing if local choices lead to global best.
Common Mistakes
Mistake: Assuming greedy always gives the best solution without checking coin set
Fix: Test greedy on examples and understand coin denominations before trusting greedy
Mistake: Not handling leftover amount when greedy fails to form exact amount
Fix: Add checks or fallback to other methods like dynamic programming
Summary
Greedy picks the best immediate choice hoping for the best overall result.
Use greedy when local best choices lead to global best, like standard coin sets.
The key insight is greedy works only if local choices never block better future options.

Practice

(1/5)
1. What is the main reason a greedy algorithm works correctly for some problems?
easy
A. Because it makes the best choice at each step hoping for a global optimum
B. Because it tries all possible solutions and picks the best one
C. Because it uses recursion to explore all options
D. Because it sorts the input data before processing

Solution

  1. Step 1: Understand greedy choice property

    A greedy algorithm picks the best option available at the current step without reconsidering previous choices.
  2. Step 2: Connect greedy choice to global optimum

    For some problems, making the best local choice at each step leads to the best overall solution.
  3. Final Answer:

    Because it makes the best choice at each step hoping for a global optimum -> Option A
  4. Quick Check:

    Greedy choice property = Because it makes the best choice at each step hoping for a global optimum [OK]
Hint: Greedy picks best local choice hoping for best overall [OK]
Common Mistakes:
  • Thinking greedy tries all solutions
  • Confusing greedy with recursion or backtracking
  • Assuming sorting alone makes greedy correct
2. Which of the following is the correct syntax to pick the next item greedily from a sorted array arr in C?
easy
A. int next = arr[--i];
B. int next = arr[i]; i++;
C. int next = arr[++i];
D. int next = arr[i]; i--;

Solution

  1. Step 1: Understand post-increment vs pre-increment

    Post-increment i++ returns current value then increments; pre-increment ++i increments then returns.
  2. Step 2: Choose syntax that picks current item then moves forward

    int next = arr[i]; i++; picks current element and then increments index for next pick.
  3. Final Answer:

    int next = arr[i]; i++; -> Option B
  4. Quick Check:

    Pick current then increment index = int next = arr[i]; i++; [OK]
Hint: Pick current element then increment index separately [OK]
Common Mistakes:
  • Using pre-increment which skips first element
  • Decrementing index instead of incrementing
  • Confusing post-increment inside array index
3. Consider the following C code that tries to select intervals greedily by earliest finish time:
typedef struct {
  int start;
  int end;
} Interval;

int main() {
  Interval arr[] = {{1,4}, {3,5}, {0,6}, {5,7}, {8,9}};
  int n = 5, count = 0, last_end = 0;
  for (int i = 0; i < n; i++) {
    if (arr[i].start >= last_end) {
      count++;
      last_end = arr[i].end;
    }
  }
  printf("%d\n", count);
  return 0;
}
What is the output?
medium
A. 3
B. 4
C. 5
D. 2

Solution

  1. Step 1: Trace interval selection without sorting

    Intervals are checked in given order: {1,4}, {3,5}, {0,6}, {5,7}, {8,9}. - Pick {1,4} (start 1 >= 0), count=1, last_end=4 - {3,5} start 3 < 4 skip - {0,6} start 0 < 4 skip - {5,7} start 5 >= 4 pick, count=2, last_end=7 - {8,9} start 8 >= 7 pick, count=3, last_end=9
  2. Step 2: Check if output matches options

    Count is 3, but 2 is 2, so check carefully: initial last_end=0, first interval start=1 >=0 pick count=1 Second interval start=3 < 4 skip Third start=0 < 4 skip Fourth start=5 >=4 pick count=2 Fifth start=8 >=7 pick count=3 Output is 3
  3. Final Answer:

    3 -> Option A
  4. Quick Check:

    Greedy without sorting picks 3 intervals [OK]
Hint: Without sorting, greedy may pick fewer intervals [OK]
Common Mistakes:
  • Assuming intervals are sorted by end time
  • Counting all intervals without checking overlap
  • Confusing start and end comparisons
4. The following code tries to solve the coin change problem greedily by picking the largest coin first. What is the bug?
int coins[] = {25, 10, 5, 1};
int amount = 30, count = 0;
for (int i = 0; i < 4; i++) {
  while (amount >= coins[i]) {
    amount -= coins[i];
    count++;
  }
}
printf("%d\n", count);
medium
A. The coin array is not sorted in descending order
B. The amount variable should be reset inside the loop
C. Greedy fails for some amounts, so this may not give minimum coins
D. The loop should run backwards from smallest coin

Solution

  1. Step 1: Understand greedy coin change approach

    The code picks largest coin repeatedly until amount is reduced, then moves to smaller coins.
  2. Step 2: Identify when greedy fails

    Greedy works for US coins but fails for some coin sets or amounts (e.g., coins {10,6,1} and amount 12). Here, greedy may not minimize coin count.
  3. Final Answer:

    Greedy fails for some amounts, so this may not give minimum coins -> Option C
  4. Quick Check:

    Greedy coin change can fail minimum count [OK]
Hint: Greedy coin change not always minimal [OK]
Common Mistakes:
  • Thinking sorting fixes greedy failure
  • Changing loop direction without reason
  • Resetting amount inside loop incorrectly
5. You want to schedule the maximum number of non-overlapping meetings from this list:
struct Meeting { int start; int end; };
Meeting meetings[] = {{0,10}, {1,3}, {4,5}};
int n = 3;
Which approach guarantees the maximum meetings scheduled and why does a greedy approach based on earliest start time fail here?
hard
A. Sort by longest duration and pick greedily; shortest duration fails because it picks too many meetings
B. Sort by earliest start time and pick greedily; earliest finish time fails because it ignores start times
C. Pick meetings randomly; sorting is not needed for maximum scheduling
D. Sort by earliest finish time and pick greedily; earliest start time fails because it may pick long meetings blocking others

Solution

  1. Step 1: Identify correct greedy strategy for interval scheduling

    Sorting meetings by earliest finish time and picking those that start after last chosen meeting's end maximizes count.
  2. Step 2: Explain why earliest start time fails

    Picking by earliest start time may select long meetings first, blocking many others, reducing total count.
  3. Final Answer:

    Sort by earliest finish time and pick greedily; earliest start time fails because it may pick long meetings blocking others -> Option D
  4. Quick Check:

    Earliest finish time sorting = max meetings [OK]
Hint: Sort by finish time, not start time, for max meetings [OK]
Common Mistakes:
  • Sorting by start time only
  • Ignoring meeting durations
  • Assuming random picks work
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard