Fractional Knapsack
Table of Contents + −
Imagine you walk into a store with a bag that holds only so much weight. There is gold dust, silver dust, and some bags of coins. You cannot carry everything. So which stuff do you grab first to walk out with the most value? That is the whole idea behind the Fractional Knapsack problem.
Here you are allowed to take a part of an item. You can scoop half the gold dust if the full amount does not fit. That one freedom changes everything. It lets a simple, fast trick give you the perfect answer.
📚 What Is the Fractional Knapsack?
You have a bag with a fixed weight limit. You call it the capacity. You also have a list of items. Each item has a weight and a value.
Your job is to fill the bag so the total value is as high as possible. The special rule here is that you can take a fraction of any item. A fraction means a part of it, like 0.5 of an item, not just the full thing or nothing.
So for each item you have a choice:
- Take the whole item.
- Take just a part of it.
- Skip it.
This is different from the 0/1 knapsack, where you must either take the full item or leave it. No parts allowed there. We will come back to that difference, because it is the reason the easy trick works here but not there.
Note
A real-world picture: think of a tanker filling jugs with oil of different prices per litre. The oil pours freely, so you can stop at any amount. That “stop at any amount” is exactly what fractional means.
🎯 The Greedy Idea
Here is the pain. There can be huge numbers of ways to fill the bag. Checking all of them is slow. So we want a rule that picks the right item every single time without trying everything.
The rule is simple. Always grab the item that gives you the most value for each unit of weight. We call that the value-per-weight ratio. It is just value / weight for an item.
Why does this work? See, every kilogram of space in your bag is precious. You want each kilogram to carry as much value as it can. So you spend your space first on the item where one kilogram is worth the most. Then the next best. And so on.
Because you can take fractions, you never waste the leftover space. When the bag is almost full and the next item is too big, you just take the part that fits. The bag ends up perfectly full, packed with the highest value possible.
Tip
A choice is “greedy” when you always pick what looks best right now and never go back to change it. For Fractional Knapsack this greedy choice is not just fast, it gives the truly best answer.
🧮 A Small Example
Let us say the bag holds 50 units of weight. We have three items.
| Item | Value | Weight | Ratio (value / weight) |
|---|---|---|---|
| A | 60 | 10 | 6.0 |
| B | 100 | 20 | 5.0 |
| C | 120 | 30 | 4.0 |
Now we sort by ratio, highest first. That gives us A, then B, then C. Let us fill the bag.
- Take all of A. Weight used is 10. Value so far is 60. Space left is 40.
- Take all of B. Weight used is 30. Value so far is 160. Space left is 20.
- Now C weighs 30 but only 20 space is left. So take the fraction
20 / 30, which is two-thirds. That part of C is worth120 * (20 / 30) = 80. Value so far is 240.
The bag is full. The best total value is 240. No other mix beats it.
Total value = 60 + 100 + 80 = 240🪜 Steps to Solve It
Before we write code, here is the plan in plain steps.
- For each item, work out its ratio, that is
value / weight. - Sort all items by this ratio, from highest to lowest.
- Start with an empty bag and a total value of 0.
- Go through the sorted items one by one:
- If the whole item fits in the space left, take it all. Add its full value. Reduce the space left by its weight.
- If it does not fully fit, take only the fraction that fits. Add that fraction of its value. The bag is now full, so stop.
- The total value you collected is the answer.
💻 The Code
Now let us turn those steps into code. We make a function that takes the capacity and the list of items, sorts by ratio, then fills the bag. We use the same example, so every language should print 240.00.
def fractional_knapsack(capacity, items): # items is a list of (value, weight) pairs. # Sort by ratio value / weight, highest first. items.sort(key=lambda it: it[0] / it[1], reverse=True)
total_value = 0.0 space_left = capacity
for value, weight in items: if weight <= space_left: # Whole item fits, take it all. space_left -= weight total_value += value else: # Take only the fraction that fits. fraction = space_left / weight total_value += value * fraction break # Bag is full now.
return total_value
items = [(60, 10), (100, 20), (120, 30)]capacity = 50
best = fractional_knapsack(capacity, items)print(f"Maximum value in the bag: {best:.2f}")The output of the above code will be:
Maximum value in the bag: 240.00Tip
The slow part of this whole thing is the sorting. Sorting takes O(n log n) time, where n is the number of items. After that we just walk through the list once, which is O(n). So the total time is O(n log n). The extra memory is O(1) if we sort the list in place, since we only keep a running total and the space left.
⚖️ Why Greedy Fails for 0/1 Knapsack
Now a quick but important contrast. The same greedy ratio trick does not give the best answer for the 0/1 knapsack. Remember, in 0/1 you cannot take parts. Each item is all or nothing.
Picture a bag that holds 10 units. There are three items, and they all share the same ratio of 10.0. Item X is value 60 at weight 6. Item Y is value 50 at weight 5. Item Z is value 50 at weight 5. Greedy grabs X first, so it fills 6 and leaves 4. Now neither Y nor Z fits whole. So greedy has to stop at a value of 60. But picking Y and Z instead gives 100, and it fills the bag exactly. Greedy lost.
The lesson is short. When you can take fractions, greedy is perfect. When it is all-or-nothing, greedy can be fooled, and you need a different method called dynamic programming. Dynamic programming is a method that builds the answer from smaller solved pieces. The link to that version is at the bottom.
Caution
Do not reach for the greedy ratio trick on a 0/1 knapsack problem in an interview. It is a classic trap. Greedy is only correct when fractions are allowed.
🧾 Complexity Summary
Here is the cost of the fractional knapsack at a glance.
| Step | Time | Why |
|---|---|---|
| Sort items by ratio | O(n log n) | We compare and order all n items. |
| Fill the bag | O(n) | One pass through the sorted items. |
| Total time | O(n log n) | Sorting is the heaviest part. |
| Extra space | O(1) | Just a running total and the space left. |
🧩 What You’ve Learned
- ✅ The Fractional Knapsack lets you take a part of an item, not just the whole thing or nothing.
- ✅ The greedy rule is to pick items by the highest value-per-weight ratio first.
- ✅ When the last item does not fully fit, you take only the fraction that fits, so the bag ends up perfectly full.
- ✅ This greedy approach gives the truly best answer, and it runs in
O(n log n)time because of the sort. - ✅ The same greedy trick fails for the 0/1 knapsack, where you need dynamic programming instead.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
In the Fractional Knapsack problem, what are you allowed to do that you cannot do in 0/1 Knapsack?
Why: The defining feature is that you may take a part of an item, not just all of it or none.
- 2
Which rule does the greedy approach use to decide the order of items?
Why: Each unit of space should carry the most value, so we sort by value divided by weight, highest first.
- 3
What is the overall time complexity of the Fractional Knapsack greedy solution?
Why: Sorting the items by ratio costs O(n log n), and that dominates the single O(n) fill pass.
- 4
Why does the same greedy ratio trick fail for the 0/1 Knapsack?
Why: Without fractions you may be forced to leave space empty, so the greedy choice can miss the best combination.