Jaconir

Greedy Algorithms

Learn the intuitive approach of making the best local choice at each step, and understand when this simple strategy leads to a global optimum.

What Is a Greedy Algorithm?

A greedy algorithm builds up a solution piece by piece, always choosing the next piece that offers the most obvious and immediate benefit. Think about giving change for 41 cents using standard US coins (25, 10, 5, 1). The greedy approach is what a human does naturally: take the biggest coin first (a quarter), then the biggest coin for the remainder (a dime), and so on. In this case, 25 + 10 + 5 + 1 works.

This strategy is appealing because it's simple and fast. However, the catch is that it doesn't always work. The greedy choice property—where a locally optimal choice leads to a globally optimal solution—only holds for certain types of problems. A key part of mastering greedy algorithms is learning to identify these problems and knowing when a more complex approach like Dynamic Programming is necessary.

Problem: Coin Change
The greedy approach for making change is simple: always pick the largest coin that is less than or equal to the remaining amount. This works for standard coin systems (like USD) but can fail for others.
[25,10,5,1]
1function greedyCoinChange(coins, amount) {
2 coins.sort((a, b) => b - a); // Largest first
3 let count = 0;
4 let result = [];
5
6 for (const coin of coins) {
7 while (amount >= coin) {
8 amount -= coin;
9 result.push(coin);
10 }
11 }
12
13 if (amount === 0) {
14 return result; // Optimal
15 }
16 return null; // Failed to make change
17}
Problem: Fractional Knapsack
You have a knapsack that can hold a certain weight, and a set of items, each with a weight and a value. You can take fractions of items. The greedy strategy is to always take as much as possible of the item with the highest value-to-weight ratio.

Item A

W: 10, V: 60

Ratio: 6

Item B

W: 20, V: 100

Ratio: 5

Item C

W: 30, V: 120

Ratio: 4
Total Value: $0.00 | Remaining Capacity: 50kg
Start with an empty knapsack. Capacity: 50kg.
1function fractionalKnapsack(capacity, items) {
2 // 1. Calculate value/weight ratio and sort
3 items.forEach(item => item.ratio = item.value / item.weight);
4 items.sort((a, b) => b.ratio - a.ratio);
5
6 let totalValue = 0;
7 let currentWeight = 0;
8
9 for (const item of items) {
10 if (currentWeight + item.weight <= capacity) {
11 // 2. Take the whole item
12 currentWeight += item.weight;
13 totalValue += item.value;
14 } else {
15 // 3. Take a fraction of the item
16 const remainingWeight = capacity - currentWeight;
17 totalValue += item.ratio * remainingWeight;
18 currentWeight += remainingWeight;
19 break; // Knapsack is full
20 }
21 }
22 return totalValue;
23}
Problem: Activity Selection
Given a set of activities with start and end times, find the maximum number of non-overlapping activities. The greedy choice is to always select the activity that finishes earliest.
ID: 1(1-4)
ID: 2(3-5)
ID: 3(0-6)
ID: 4(5-7)
ID: 5(3-9)
ID: 6(5-9)
ID: 7(6-10)
ID: 8(8-11)
ID: 9(8-12)
ID: 10(2-14)
ID: 11(12-16)
Start. Sort activities by their finish times.
1function activitySelection(activities) {
2 // 1. Sort activities by finish time
3 activities.sort((a, b) => a.end - b.end);
4
5 const result = [];
6 if (activities.length === 0) return result;
7
8 // 2. Select the first activity
9 result.push(activities[0]);
10 let lastFinishTime = activities[0].end;
11
12 for (let i = 1; i < activities.length; i++) {
13 const currentActivity = activities[i];
14
15 // 3. If current activity starts after the last one finished...
16 if (currentActivity.start >= lastFinishTime) {
17 // ...select it and update the last finish time.
18 result.push(currentActivity);
19 lastFinishTime = currentActivity.end;
20 }
21 }
22 return result;
23}
Coding Challenge
You are given an integer array `nums`. You are initially positioned at the array's first index, and each element in the array represents your maximum jump length at that position. Return `true` if you can reach the last index, or `false` otherwise.
Go Deeper with "Grokking Algorithms"

"Grokking Algorithms" by Aditya Bhargava has one of the best and most accessible introductions to greedy algorithms, using clear illustrations to explain problems like the knapsack and set covering.

J
Dafin Edison J
Creator & Developer of Jaconir

I build things for the web. From immersive games to practical tools, my goal is to create products that people love to use and to share the knowledge I've gained along the way.