Fractional Knapsack Problem in DSA Java - Time & Space Complexity
We want to understand how the time needed to solve the Fractional Knapsack Problem changes as the number of items grows.
Specifically, how does the sorting and selection process scale with more items?
Analyze the time complexity of the following code snippet.
class Item {
int value, weight;
Item(int v, int w) { value = v; weight = w; }
}
void fractionalKnapsack(Item[] items, int capacity) {
Arrays.sort(items, (a, b) -> Double.compare((double)b.value / b.weight, (double)a.value / a.weight));
int currentWeight = 0;
double totalValue = 0.0;
for (Item item : items) {
if (currentWeight + item.weight <= capacity) {
currentWeight += item.weight;
totalValue += item.value;
} else {
int remain = capacity - currentWeight;
totalValue += item.value * ((double) remain / item.weight);
break;
}
}
}
This code sorts items by value per weight and then picks whole or fractional parts to maximize total value within capacity.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sorting the array of items by value-to-weight ratio.
- How many times: Sorting compares items multiple times, roughly proportional to n log n where n is number of items.
- Secondary operation: Single loop through items to pick fractions or whole items, runs n times.
As the number of items increases, sorting takes more time, growing faster than just going through items once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log(10) ≈ 33 operations for sorting + 10 for picking |
| 100 | About 100 * log(100) ≈ 664 operations for sorting + 100 for picking |
| 1000 | About 1000 * log(1000) ≈ 9965 operations for sorting + 1000 for picking |
Pattern observation: Sorting dominates and grows faster than linearly, while picking grows linearly.
Time Complexity: O(n log n)
This means the time needed grows a bit faster than the number of items because of sorting, but the picking step grows linearly.
[X] Wrong: "The fractional knapsack can be solved in linear time because we just pick items until full."
[OK] Correct: We must first sort items by value per weight, which takes more than linear time, so the sorting step dominates the total time.
Understanding this time complexity helps you explain why sorting is necessary before selection, a key insight interviewers look for.
"What if the items were already sorted by value per weight? How would the time complexity change?"
Practice
Fractional Knapsack Problem?Solution
Step 1: Understand problem objective
The fractional knapsack problem allows taking parts of items to maximize total value without exceeding weight limit.Step 2: Compare options
Maximize total value by taking fractions of items within weight limit correctly states maximizing value by taking fractions. Others focus on minimizing weight or whole items only, which is incorrect.Final Answer:
Maximize total value by taking fractions of items within weight limit -> Option DQuick Check:
Goal = Maximize value with fractions [OK]
- Thinking only whole items can be taken
- Confusing weight minimization with value maximization
- Ignoring fractional parts possibility
Solution
Step 1: Identify sorting criteria
We must sort by value-to-weight ratio in descending order to pick best value fractions first.Step 2: Check code correctness
Arrays.sort(items, (a, b) -> Double.compare((double)b.value / b.weight, (double)a.value / a.weight)); sorts by ratio ((double)b.value/b.weight vs (double)a.value/a.weight) descending. Others sort by weight or value only, which is incorrect.Final Answer:
Arrays.sort(items, (a, b) -> Double.compare((double)b.value / b.weight, (double)a.value / a.weight)); -> Option AQuick Check:
Sort by ratio descending = Arrays.sort(items, (a, b) -> Double.compare((double)b.value / b.weight, (double)a.value / a.weight)); [OK]
- Sorting by weight or value alone
- Sorting in ascending order instead of descending
- Using integer division instead of double
class Item {
int value, weight;
Item(int v, int w) { value = v; weight = w; }
}
Item[] items = {new Item(60, 10), new Item(100, 20), new Item(120, 30)};
int W = 50;
double maxValue = 0;
Arrays.sort(items, (a, b) -> Double.compare((double)b.value / b.weight, (double)a.value / a.weight));
int remaining = W;
for (Item item : items) {
if (item.weight <= remaining) {
maxValue += item.value;
remaining -= item.weight;
} else {
maxValue += item.value * ((double)remaining / item.weight);
break;
}
}
System.out.println((int)maxValue);Solution
Step 1: Sort items by value/weight ratio
Ratios: 60/10=6, 100/20=5, 120/30=4. Sorted order: (60,10), (100,20), (120,30).Step 2: Calculate max value with weight limit 50
Take full (60,10): value=60, remaining=40
Take full (100,20): value=160, remaining=20
Take fraction of (120,30): fraction=20/30=2/3, value added=120*(2/3)=80
Total value=60+100+80=240 but code casts to int after adding fractions, so 240.Final Answer:
240 -> Option CQuick Check:
Sum values with fractions = 240 [OK]
- Not sorting by ratio correctly
- Taking items in wrong order
- Incorrect fraction calculation
int maxValue = 0;
for (Item item : items) {
if (item.weight <= W) {
maxValue += item.value;
W -= item.weight;
} else {
maxValue += item.value * (W / item.weight);
break;
}
}Solution
Step 1: Analyze fraction calculation
Expression (W / item.weight) uses integer division, truncating fraction to 0 or 1 incorrectly.Step 2: Correct fraction calculation
It should use floating division: (double)W / item.weight to get correct fraction value.Final Answer:
Using integer division in fraction calculation causes wrong value -> Option BQuick Check:
Integer division in fraction = error [OK]
- Forgetting to cast to double in fraction
- Failing to sort items by value-to-weight ratio before iterating
- Declaring maxValue as int but adding fractions
Solution
Step 1: Calculate value-to-weight ratios and sort
Ratios:
(40/2)=20, (100/20)=5, (50/10)=5, (60/12)=5
Sorted order: (40,2), (100,20), (50,10), (60,12)Step 2: Pick items to maximize value within capacity 30
Take full (40,2): value=40, remaining=28
Take full (100,20): value=140, remaining=8
Next (50,10): only 8 weight left, fraction=8/10=0.8, value added=50*0.8=40
Total value=40+100+40=180Step 3: Check if next item can add value
Last item (60,12) cannot be taken as capacity is full.Final Answer:
180 -> Option AQuick Check:
Sum values with fractions = 180 [OK]
- Ignoring highest ratio item first
- Taking items in wrong order
- Not calculating fraction correctly
Ready to prove it?
Pass the test and this pattern moves unknown
