Fractional Knapsack
A greedy algorithm that fills the knapsack by value per unit of weight when items can be split, giving the best result.
Worth knowing first
#How does it work?
Fractional knapsack is the version of 0/1 knapsack where items can be split: we may take any amount of an item, not just all or nothing (think gold dust, spices or fabric).
Here the greedy approach is optimal: sort items by value per unit of weight (v / w), take whole items starting with the most valuable, then cut the first item that doesn't fit to fill the remaining space, and stop.
With the same items, 0/1 knapsack's best value for capacity 7 is 9; the fractional version reaches 9.67. In the 0/1 version the same greedy rule can fail, because items can't be split to use the leftover space. That is why 0/1 knapsack needs DP.
#Try it yourself
| w | v | v/w | × | + | |
|---|---|---|---|---|---|
| 4 | 5 | 7 | 1.4 | ||
| 2 | 3 | 4 | 1.33 | ||
| 3 | 4 | 5 | 1.25 | ||
| 1 | 1 | 1 | 1 |
Capacity left
7 / 7Items can be split (think dust, liquid, fabric). The greedy rule: start with the best value per unit of weight.
#Step by step
- 01Compute v / w for each item.
- 02Sort the items by that ratio, largest first.
- 03Take every item that fits whole.
- 04From the first item that doesn't fit, take the fraction that fills the remaining capacity and stop.
#Example code
The same algorithm in 8 languages. Every program is compiled, run and checked to print the same output.
# (weight, value) of each item; any fraction of an item may be taken.
ITEMS = [(1, 1), (3, 4), (4, 5), (5, 7)]
def fractional_knapsack(items: list, capacity: float) -> float:
total = 0.0
for w, v in sorted(items, key=lambda it: it[1] / it[0], reverse=True): # best value per weight first
if capacity <= 0:
break
take = min(w, capacity) # the whole item, or the part that still fits
total += v * take / w
capacity -= take
return total
print(f"{fractional_knapsack(ITEMS, 7):.2f}") # 0/1 knapsack only reaches 9#Complexity
| Operation | Time |
|---|---|
| Sorting | O(n log n) |
| Filling | O(n) |
| Total | O(n log n) |
| 0/1 version (DP) | O(n · W) |
Sorting dominates. With a selection algorithm, finding the item to cut can even be done in O(n). The result is always optimal: a unit from a lower-ratio item can never beat a unit from a higher-ratio one.
#When to use it?
Sharing out divisible resources: budget allocation, cargo and fuel planning, fractional investment amounts. It is also used to compute upper bounds in branch-and-bound solvers for 0/1 knapsack.
#Practice
Log in to answer questions and save your progress.
Easy
In what order are items taken in fractional knapsack?
- 1By value per weight (v / w), highest first
- 2By weight, lightest first
- 3By value, highest first
- 4At random
What is the difference between 0/1 and fractional knapsack?
- 1In the fractional version part of an item can be taken
- 2The fractional version has no capacity limit
- 3In 0/1 items can be split
- 4There is no difference
What is fractional knapsack's time complexity?
- 1O(n log n)
- 2O(n · W)
- 3O(2ⁿ)
- 4O(W)
Medium
Capacity 5; items (weight, value): (4, 8), (2, 3). What is the best value?
- 19.5
- 28
- 311
- 410
Hard
Why can the same greedy rule fail for 0/1 knapsack?
- 1Items can't be split, so leftover space may go to waste
- 2Because ratios can be negative
- 3Because sorting gives a wrong order
- 4It can't; it is always correct