Algorithm

Fractional Knapsack

Greedy & Intervals Pattern

Fractional Knapsack

You are given n items, where item i has a positive weight and a positive value, and a knapsack that can carry a total weight of at most W. Unlike the 0/1 knapsack, you may take a fractional part of any item, gaining that fraction of its value for that fraction of its weight. Return the maximum total value you can carry. The answer may be fractional.

CONSTRAINTS
  • 1 ≤ n ≤ 10⁵
  • 1 ≤ W ≤ 10⁵
  • 1 ≤ value, weight ≤ 10⁴ for every item
  • Any fraction of an item may be taken, gaining a proportional value
EXAMPLE 1
Input: W = 50, items = [(60,10),(100,20),(120,30)]
Output: 240.0
Take the first two items whole for 160, then two-thirds of the third to fill the remaining 20 units of capacity, adding 80. The third item is split precisely because fractions are allowed.
EXAMPLE 2
Input: W = 10, items = [(60,10),(100,20),(120,30)]
Output: 60.0
The whole capacity is spent on the densest item at 6.0 per unit weight; nothing else fits and no other item is denser.
EXAMPLE 3
Input: W = 5, items = [(10,10)]
Output: 5.0
Only half of the single item fits, yielding half of its value.
EXAMPLE 4
Input: W = 100, items = [(10,2),(5,1)]
Output: 15.0
Both items fit entirely within the generous capacity, so their full values are taken and leftover space is simply unused.
EXAMPLE 5
Input: W = 3, items = [(6,3),(6,2)]
Output: 8.0
The second item is denser at 3.0 per unit versus 2.0, so it is taken whole for 6, and the remaining 1 unit of capacity takes a third of the first item for 2 — total 8, beating taking the first item whole for 6.
Can I really take a fraction of an item?
Yes — that is the defining feature of this version and the reason greedy works. If items were all-or-nothing, this would be the 0/1 knapsack, where the same greedy is provably wrong and a dynamic-programming table is required.
What do I sort by?
Value divided by weight, the value density, in descending order. Sorting by value alone or weight alone gives wrong answers, because neither captures efficiency per unit of the constrained resource.
Is the answer allowed to be a non-integer?
Yes, since taking a fraction of an item produces a fractional value. The return type should be a real number.
Does leftover capacity matter?
No, unused capacity is free and never penalised. Greedy fills until either the items run out or the bag is exactly full, whichever comes first.
One rule changes everything

This is the knapsack you have met before — a weight budget, items with weight and value, maximise the value you carry — with a single relaxation: you may take a fraction of an item. Take a third of an item and you get a third of its value for a third of its weight.

That one change turns a hard problem into an easy one, and understanding why is the whole lesson, because it teaches you exactly when greedy is legal and when it is not.

Why 0/1 was hard and this is easy

Recall the ordinary 0/1 knapsack: each item is all-or-nothing. There, a greedy rule like "take the most valuable-per-kilo item first" fails, because taking it might leave an awkward gap of unused capacity that nothing fits into. The items are indivisible, so how well things pack together matters as much as how good they are individually, and no per-item ranking can see that packing. That is why 0/1 needs a dynamic-programming table.

Fractions destroy the packing problem entirely. There is never an awkward gap, because whatever space is left over can always be filled with a slice of the next item. Once "does it fit?" stops mattering, the only thing that matters is efficiency — getting the most value out of each kilo of capacity.

The greedy choice, and its proof

Define each item's value density as value / weight — the value you get per unit of weight. The greedy rule: sort items by density, highest first, and pour capacity into the densest item until it runs out or the bag fills; if an item does not fully fit, take exactly the fraction that fills the remaining space, and stop.

Here is why it is optimal — an exchange argument, the same tool as every greedy page. Suppose an optimal packing contains some amount of a lower-density item while a higher-density item is not fully used. Take a tiny slice of weight w out of the low-density item and replace it with w worth of the high-density item. The weight is unchanged, so the bag is still legal, but the value strictly increases, because the same weight of a denser item is worth more. So the packing was not optimal after all — contradiction. Therefore an optimal packing always fills from densest downward, which is exactly what greedy does. The fractional freedom is what makes the swap always possible: we can move any amount of weight, not just whole items.

Crucial Notethis proof leans entirely on being able to swap arbitrary fractions. In the 0/1 world you cannot take a slice of weight w — you must move a whole item — and the swap can overflow or underflow the bag, so the argument collapses. That is the precise reason the identical-looking greedy is correct here and wrong there. When you meet a knapsack, the very first question is: whole items only, or fractions allowed? The answer decides greedy-versus-DP.
The algorithm
python
def fractional_knapsack(items, capacity):
    # items = [(value, weight), ...]
    items.sort(key=lambda it: it[0] / it[1], reverse=True)   # densest first
    total = 0.0
    for value, weight in items:
        if capacity >= weight:
            total += value                 # whole item fits
            capacity -= weight
        else:
            total += value * (capacity / weight)   # take the fraction that fills the bag
            break                          # bag is now full
    return total

Sorting by density is O(N log N) and dominates; the fill pass is O(N).

Worked Example:W = 50, items (value, weight) = (60,10), (100,20), (120,30)
Densities: 60/10 = 6.0, 100/20 = 5.0, 120/30 = 4.0. Already in descending order.
- Item (60,10): fits. Take it all. Value 60, capacity left 40.
- Item (100,20): fits. Take it all. Value 160, capacity left 20.
- Item (120,30): does not fit in 20. Take 20/30 = two-thirds of it: value adds 120 × (20/30) = 80. Value 240, bag full, stop.

Answer 240.0. Notice the last item was split — that slice is what makes fractional knapsack strictly more valuable than the 0/1 version on the same input, where you could not have taken the partial third item.

The lesson

The reusable idea is not "sort by density" — it is identify what actually constrains the problem, and check whether the greedy swap is legal. For fractional knapsack the constraint reduced to pure efficiency, and arbitrary swaps were legal, so greedy won. For 0/1 knapsack the constraint included packing, swaps were not free, and greedy lost to dynamic programming.

So the transferable habit, reinforced from every page in this section: greedy is only as valid as the exchange argument behind it. Before sorting by any key, ask whether you can locally improve any non-greedy solution toward the greedy one without breaking a constraint. If the improvement is always possible — as it is when you can move fractions — greedy is safe. If some constraint blocks the improvement — indivisibility, ordering, a global balance — greedy probably fails and you need a table.

Recognition signal for the fractional-greedy shape specifically: you are allocating a divisible budget (weight, money, time, bandwidth) across options to maximise a linear return, with no packing or ordering constraint. Sort by return-per-unit-budget and pour. The moment the resource becomes indivisible, or the options interact, that signal switches off.

Interactive Strategy Visualization

Density-First Filling

Sorted Items (Density)
A
$6010kg
DENSITY
$6/kg
B
$10020kg
DENSITY
$5/kg
C
$12030kg
DENSITY
$4/kg
Bag Value
$0
Capacity Used: 0/50kg
Goal: Fill capacity 50 with max value. Items sorted by Density.
CORE LOGIC

Calculate the Value/Weight ratio for every item. Sort descending.

OPTIMALITY

Greedily taking the highest density item guarantees the best "bang for buck" since we can take fractions.

Exponential Try Every Subset
O(N log N) Time Greedy by Density