Fractional Knapsack Problem in DSA Go - 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 sorting and selecting fractions affect the total steps?
Analyze the time complexity of the following code snippet.
package main
import (
"fmt"
"sort"
)
type Item struct {
value, weight float64
}
func fractionalKnapsack(items []Item, capacity float64) float64 {
sort.Slice(items, func(i, j int) bool {
return items[i].value/items[i].weight > items[j].value/items[j].weight
})
totalValue := 0.0
for _, item := range items {
if capacity == 0 {
break
}
if item.weight <= capacity {
totalValue += item.value
capacity -= item.weight
} else {
totalValue += item.value * (capacity / item.weight)
capacity = 0
}
}
return totalValue
}
func main() {
items := []Item{{60, 10}, {100, 20}, {120, 30}}
capacity := 50.0
fmt.Println(fractionalKnapsack(items, capacity))
}
This code sorts items by value per weight and then picks whole or fractional parts until capacity is full.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sorting the items by value-to-weight ratio.
- How many times: Sorting takes about n log n steps for n items.
- Secondary operation: One loop through all items to pick fractions or whole items.
- How many times: This loop runs n times.
As the number of items (n) grows, sorting takes more steps, roughly n log n, while the picking loop grows linearly with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log 10 + 10 ≈ 43 steps |
| 100 | About 100 * log 100 + 100 ≈ 700 steps |
| 1000 | About 1000 * log 1000 + 1000 ≈ 10,000 steps |
Pattern observation: Sorting dominates and grows faster than the linear picking loop.
Time Complexity: O(n log n)
This means the time needed grows a bit faster than just the number of items because sorting takes extra steps.
[X] Wrong: "The picking loop is the slowest part, so the complexity is O(n)."
[OK] Correct: Sorting the items first takes more time than just picking, so sorting controls the overall speed.
Understanding this time complexity helps you explain why sorting is important before selection and shows you can analyze combined steps clearly.
"What if the items were already sorted by value-to-weight ratio? How would the time complexity change?"
Practice
Fractional Knapsack Problem?Solution
Step 1: Understand the problem goal
The fractional knapsack problem allows taking parts of items to maximize total value without exceeding weight capacity.Step 2: Identify the correct objective
The goal is to maximize value by possibly taking fractions, not just whole items or minimizing weight.Final Answer:
Maximize the total value by taking fractions of items within the weight limit -> Option DQuick Check:
Goal = Maximize value with fractions [OK]
- Thinking only whole items can be taken
- Confusing weight limit with item count limit
- Assuming minimizing weight is the goal
Solution
Step 1: Identify sorting criteria for fractional knapsack
Items must be sorted by value-to-weight ratio in descending order to pick the best value per weight first.Step 2: Check each option's sorting logic
sort.Slice(items, func(i, j int) bool { return items[i].value/items[i].weight > items[j].value/items[j].weight }) sorts by value/weight descending, which is correct. Others sort by weight or value incorrectly.Final Answer:
sort.Slice(items, func(i, j int) bool { return items[i].value/items[i].weight > items[j].value/items[j].weight }) -> Option CQuick Check:
Sort by value/weight descending = sort.Slice(items, func(i, j int) bool { return items[i].value/items[i].weight > items[j].value/items[j].weight }) [OK]
- Sorting by weight only
- Sorting by value only
- Using ascending order instead of descending
type Item struct {
value, weight float64
}
items := []Item{{60, 10}, {100, 20}, {120, 30}}
capacity := 50.0
// Sort by value/weight descending
sort.Slice(items, func(i, j int) bool {
return items[i].value/items[i].weight > items[j].value/items[j].weight
})
var totalValue float64
for _, item := range items {
if capacity == 0 {
break
}
if item.weight <= capacity {
capacity -= item.weight
totalValue += item.value
} else {
fraction := capacity / item.weight
totalValue += item.value * fraction
capacity = 0
}
}
fmt.Printf("%.2f", totalValue)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: Pick items until capacity 50
Take full {60,10} (capacity=40, value=60), full {100,20} (capacity=20, value=160), then fraction of {120,30} with 20 weight (fraction=20/30=2/3), value added=120*(2/3)=80, total=240.Final Answer:
240.00 -> Option AQuick Check:
Total value = 60 + 100 + 80 = 240.00 [OK]
- Not sorting by value/weight ratio
- Taking items without checking capacity
- Incorrect fraction calculation
type Item struct {
value, weight float64
}
items := []Item{{60, 10}, {100, 20}, {120, 30}}
capacity := 50.0
sort.Slice(items, func(i, j int) bool {
return items[i].value > items[j].value
})
var totalValue float64
for _, item := range items {
if capacity == 0 {
break
}
if item.weight <= capacity {
capacity -= item.weight
totalValue += item.value
} else {
fraction := capacity / item.weight
totalValue += item.value * fraction
capacity = 0
}
}
fmt.Printf("%.2f", totalValue)Solution
Step 1: Analyze sorting criteria
The code sorts by value only, which is incorrect for fractional knapsack; it should sort by value/weight ratio.Step 2: Identify correct fix
Sorting by value/weight ratio descending ensures maximum value per weight is chosen first, fixing the bug.Final Answer:
Sort items by value/weight ratio descending instead of value only -> Option BQuick Check:
Sort by value/weight ratio fixes selection [OK]
- Sorting by value only
- Ignoring fraction calculation
- Changing variable types unnecessarily
Solution
Step 1: Calculate value/weight ratios and sort items
Ratios: 40/2=20, 100/20=5, 50/10=5. Sorted order: {40,2}, {100,20}, {50,10}.Step 2: Pick items until capacity 15
Take full {40,2} (capacity=13, value=40), then full {50,10} (capacity=3, value=90), then fraction of {100,20} with 3 weight (fraction=3/20=0.15), value added=100*0.15=15, total=40 + 50 + 15=105.Final Answer:
105.00 -> Option AQuick Check:
Total value = 40 + 50 + 15 = 105.00 [OK]
- Not sorting by value/weight ratio
- Taking heavier items first
- Incorrect fraction calculation
Ready to prove it?
Pass the test and this pattern moves unknown
