-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathknapsack_combinations.py
117 lines (83 loc) · 2.71 KB
/
knapsack_combinations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
Given a list of weights and a max capacity of a knapsack, find all possible
combinations of items that can fit in the knapsack.
The answer should include the indexes of the items and not the items themselves.
Examples:
weights: [3, 5]
maxWeight: 8
answer:
[[0,1],[0], [1], []]
weights: [4, 7, 2, 1]
maxWeight: 7
answer:
[[0,2,3], [0,2], [0,3], [0], [1], [2,3], [2], [3], []]
-----
Algorithm:
[]
/ \
[] [4]
/ \ / \
[] [7] [4] [4,7]
/ \ / \
[] [2] [7] [7,2] <-- overweight, return
/ \
[] [1] <- do not have any elements left, add to the combinations
/
do not have any elements left, add the combination
We choose to add an item or not. If we find a combination that is
over maxWeight we stop the recursive calls.
If the combination is valid, we add to our list of combinations.
Base case:
- maxWeight < 0: return (we added a number that made it over the weight)
- position == len(weights): save current combination
Recursive step:
- Start from the first element, we can choose to add it or not.
- If we add it, we subtract it from the maxWeight and go to the next element
- Else, we do not subtract it and go to the next element
- Repeat until we are over weight or have gone through all elements
Time Complexity: O(2^n) - we have to go through all combinations
Space Complexity: O(maxWeight) - it is the deepest height of the tree we can go.
weights: [3, 5]
maxWeight: 8
len(weights) = 2
current_combination = []
position = 2
max_weight = 8
[]
/ \
[3] []
/ \ / \
[3,5] [3] [5] []
"""
def knapsack_combinations(weights, max_weight):
result = []
def rec_helper(weights, max_weight, position, current_combination):
if max_weight < 0:
return
if position == len(weights):
result.append(current_combination)
return
rec_helper(
weights,
max_weight - weights[position],
position + 1,
current_combination + [position],
)
rec_helper(
weights,
max_weight,
position + 1,
current_combination,
)
rec_helper(weights, max_weight, 0, [])
return result
def test(weights, max_weight, expected_answer):
answer = knapsack_combinations(weights, max_weight)
if answer != expected_answer:
raise Exception(
f"Answer {answer} is incorrect. Expected answer was {expected_answer}"
)
if __name__ == "__main__":
test([3, 5], 8, [[0, 1], [0], [1], []])
test([4, 7, 2, 1], 7, [[0, 2, 3], [0, 2], [0, 3], [0], [1], [2, 3], [2], [3], []])
print("All tests passed!")