Fractional Knapsack is the cleanest example of a greedy algorithm. Unlike the classic 0/1 knapsack (which needs dynamic programming), here you may take a fraction of an item — and that one freedom makes a simple greedy choice provably optimal.
Problem. You have a knapsack with a weight capacity, and a list of items, each with a value
and a weight. You may take any fraction of an item (and get that fraction of its value). Maximize
the total value you carry.
Example: capacity = 50, items (value, weight) = (60, 10), (100, 20), (120, 30) → answer 240.0
(take the first two whole, then 20/30 of the third).
The slow way first
You might think: try every combination of items, or every cut point. With fractions allowed, the number of possibilities is unbounded — and even restricting to whole-item subsets is O(2ⁿ). That is far too slow and, worse, it ignores the structure that makes this problem easy.
The question to ask: if I could add just one more kilogram to the bag, which item gives me the most value for it? The answer never changes: the item with the highest value-per-kilogram.
The idea: take the densest value first
Each item has a ratio = value / weight — its value per kilogram. Sort items by that ratio, highest first. Then walk down the list: take each item whole while it still fits, and when you reach the first item that does not fit, take just the fraction that fills the remaining space. Once the bag is full, stop.
The key insight: every kilogram of space should hold the densest value available. Because we can split items, there is never a reason to skip a denser item for a lighter one — greedy is exactly optimal.
Walk through it
Step through the animation. The three items are already sorted by ratio (6.0, 5.0, 4.0). The pick pointer scans left to right. The first two fit whole, draining the capacity meter from 50 to 40 to 20. The third weighs 30 kg but only 20 kg remains, so we take 20/30 of it for 4.0 × 20 = $80, filling the bag and reaching a total of $240.
Pseudocode
sort items by (value / weight) descending
total = 0
for each item:
if item.weight <= capacity: # fits whole
total += item.value
capacity -= item.weight
else: # does not fit
fraction = capacity / item.weight
total += item.value * fraction # take just enough to fill up
stop
return totalThe Python solution
def fractional_knapsack(items, capacity):
items.sort(key=lambda it: it.value / it.weight,
reverse=True)
total = 0.0
for it in items:
if it.weight <= capacity:
total += it.value
capacity -= it.weight
else:
fraction = capacity / it.weight
total += it.value * fraction
capacity = 0
break
return total- We sort items by
value / weightdescending, so the densest value comes first. totalaccumulates the value we have packed;capacityis the room left.- If an item fits whole (
weight <= capacity), we take all of it and shrink the capacity. - Otherwise it is the last item we touch:
fraction = capacity / weightis the portion that fits, and we add that share of its value. - The
breakends the loop — once the bag is full no later (lower-ratio) item can improve the answer.
Complexity
| Case | Time | Notes |
|---|---|---|
| Sorting the items | O(n log n) (moderate) | the dominant cost |
| Single greedy pass | O(n) (moderate) | one item at a time |
O(1) (fast)The sort dominates at O(n log n); the fill loop is a single linear pass. We use only O(1) extra space beyond the input (or O(n) if the sort is not in place).
When this pattern shows up
When a problem lets you take partial amounts and asks you to maximize or minimize a total, look for a ratio to sort by and take the best one greedily. Job scheduling by deadline, assigning cookies to children, and gas-station routing are all the same move: sort by the right key, then sweep.
Greedy works here only because fractions are allowed. In the classic 0/1 knapsack (each item is all-or-nothing) the ratio trick can be wrong — that version needs dynamic programming. Do not confuse the two in an interview.
Practice
Capacity is 50. After taking items (60,10) and (100,20) whole, how much room is left and what happens to the 30 kg item?
1. What key do we sort the items by?
2. Why is the greedy choice optimal here but not for 0/1 knapsack?
3. What is the overall time complexity?
4. When we reach an item that does not fit, what do we do?