Skip to content

Commit 836a8d0

Browse files
Optimized Recursive Knapsack with Memoization
- Added memoization to avoid redundant calculations - Improved function readability with better parameter naming - Ensured correct handling of empty inputs - Reduced time complexity from O(2ⁿ) to O(n * max_weight)
1 parent 6c92c5a commit 836a8d0

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed
+41-31
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,61 @@
1-
# To get an insight into naive recursive way to solve the Knapsack problem
2-
3-
41
"""
52
A shopkeeper has bags of wheat that each have different weights and different profits.
6-
eg.
7-
no_of_items 4
8-
profit 5 4 8 6
9-
weight 1 2 4 5
10-
max_weight 5
3+
Example:
4+
no_of_items = 4
5+
profit = [5, 4, 8, 6]
6+
weight = [1, 2, 4, 5]
7+
max_weight = 5
8+
119
Constraints:
12-
max_weight > 0
13-
profit[i] >= 0
14-
weight[i] >= 0
15-
Calculate the maximum profit that the shopkeeper can make given maxmum weight that can
16-
be carried.
10+
- max_weight > 0
11+
- profit[i] >= 0
12+
- weight[i] >= 0
13+
14+
Calculate the maximum profit the shopkeeper can make given the maximum weight that can be carried.
1715
"""
1816

17+
from functools import lru_cache
1918

20-
def knapsack(
21-
weights: list, values: list, number_of_items: int, max_weight: int, index: int
22-
) -> int:
19+
def knapsack(weights: list, values: list, number_of_items: int, max_weight: int, index: int, memo=None) -> int:
2320
"""
24-
Function description is as follows-
25-
:param weights: Take a list of weights
26-
:param values: Take a list of profits corresponding to the weights
27-
:param number_of_items: number of items available to pick from
28-
:param max_weight: Maximum weight that could be carried
29-
:param index: the element we are looking at
30-
:return: Maximum expected gain
21+
Optimized Recursive Knapsack with Memoization.
22+
23+
:param weights: List of item weights
24+
:param values: List of corresponding item profits
25+
:param number_of_items: Total number of available items
26+
:param max_weight: Maximum weight capacity of the knapsack
27+
:param index: Current item index being considered
28+
:param memo: Dictionary to store computed results for optimization
29+
:return: Maximum profit possible
30+
3131
>>> knapsack([1, 2, 4, 5], [5, 4, 8, 6], 4, 5, 0)
3232
13
33-
>>> knapsack([3 ,4 , 5], [10, 9 , 8], 3, 25, 0)
33+
>>> knapsack([3, 4, 5], [10, 9, 8], 3, 25, 0)
3434
27
3535
"""
3636
if index == number_of_items:
3737
return 0
38-
ans1 = 0
38+
39+
if memo is None:
40+
memo = {}
41+
42+
# If already computed, return stored value
43+
if (index, max_weight) in memo:
44+
return memo[(index, max_weight)]
45+
46+
# Case 1: Skip the current item
47+
ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1, memo)
48+
49+
# Case 2: Include the current item (if weight allows)
3950
ans2 = 0
40-
ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1)
4151
if weights[index] <= max_weight:
42-
ans2 = values[index] + knapsack(
43-
weights, values, number_of_items, max_weight - weights[index], index + 1
44-
)
45-
return max(ans1, ans2)
52+
ans2 = values[index] + knapsack(weights, values, number_of_items, max_weight - weights[index], index + 1, memo)
53+
54+
# Store and return the maximum value obtained
55+
memo[(index, max_weight)] = max(ans1, ans2)
56+
return memo[(index, max_weight)]
4657

4758

4859
if __name__ == "__main__":
4960
import doctest
50-
5161
doctest.testmod()

0 commit comments

Comments
 (0)