Greedy Algorithms
What is a Greedy Algorithm?
A Greedy algorithm is an algorithmic paradigm that follows the problem-solving heuristic of making the locally optimal choice at each stage with the hope of finding a global optimum.
It is generally faster and more intuitive than Dynamic Programming, but it only works if the problem satisfies two properties:
- Greedy Choice Property: A global optimum can be reached by selecting the local optimum at each step.
- Optimal Substructure: An optimal solution to the problem contains optimal solutions to its subproblems.
The Greedy vs. DP Trade-off
Greedy algorithms are often
Example: Coin Change
- Scenario: Return change for
using coins . - Greedy approach:
- Take the largest coin (
). Remaining: . - Take two
s. - Total: 3 coins.
- Take the largest coin (
- Optimal (DP) approach:
- Take two
s. - Total: 2 coins.
- Take two
Practice Exercise
- Activity Selection: Given start and finish times of activities, find the maximum number you can perform.
- Fractional Knapsack: Solve the knapsack problem where you can take pieces of items.
- Jump Game: Determine if you can reach the last index of an array.
Answer
1. Activity Selection ( Time)
The greedy strategy is to always pick the activity that finishes earliest, as this leaves the most time for subsequent activities.
public int MaxActivities(int[] start, int[] end) {
var activities = start.Zip(end, (s, e) => (s, e)).OrderBy(x => x.e).ToList();
int count = 1;
int lastEnd = activities[0].e;
for (int i = 1; i < activities.Count; i++) {
if (activities[i].s >= lastEnd) {
count++;
lastEnd = activities[i].e;
}
}
return count;
}
2. Fractional Knapsack ( Time)
Maximize value by picking items with the highest Value-to-Weight Ratio.
public double KnapsackValue(int[] val, int[] wt, int cap) {
var items = val.Zip(wt, (v, w) => new { val = v, wt = w, ratio = (double)v/w })
.OrderByDescending(x => x.ratio).ToList();
double totalValue = 0;
foreach (var item in items) {
if (cap >= item.wt) {
cap -= item.wt;
totalValue += item.val;
} else {
totalValue += item.ratio * cap;
break;
}
}
return totalValue;
}
3. Jump Game ( Time)
Maintain the “farthest reachable” index.
public bool CanJump(int[] nums) {
int farthest = 0;
for (int i = 0; i < nums.Length; i++) {
if (i > farthest) return false;
farthest = Math.Max(farthest, i + nums[i]);
}
return true;
}
Summary
Greedy algorithms are the “quick and dirty” path to optimization. They are perfect for problems like Huffman Coding, Dijkstra’s, and Minimum Spanning Trees. However, always verify their accuracy—if a problem requires looking ahead to ensure global correctness, you likely need Dynamic Programming.