Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions dynamic_programming/knapsack.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,72 @@ def knapsack(w, wt, val, n):
return dp[n][w_], dp


def knapsack_space_optimized(
capacity: int, weights: list[int], values: list[int], num_items: int
) -> int:
"""
Solve the 0/1 knapsack problem with O(capacity) extra space.

It uses a 1D dynamic programming array and iterates capacities in reverse
for each item to avoid reusing the same item more than once.

>>> knapsack_space_optimized(50, [10, 20, 30], [60, 100, 120], 3)
220
>>> knapsack_space_optimized(0, [10, 20, 30], [60, 100, 120], 3)
0
>>> knapsack_space_optimized(6, [4, 3, 2, 3], [3, 2, 4, 4], 4)
8
>>> knapsack_space_optimized(-1, [1], [1], 1)
Traceback (most recent call last):
...
ValueError: The knapsack capacity cannot be negative.
>>> knapsack_space_optimized(1, [1], [1], -1)
Traceback (most recent call last):
...
ValueError: The number of items cannot be negative.
>>> knapsack_space_optimized(1, [1], [1], 2)
Traceback (most recent call last):
...
ValueError: The number of items exceeds the provided input lengths.
>>> knapsack_space_optimized(1, [-1], [1], 1)
Traceback (most recent call last):
...
ValueError: Weight at index 0 cannot be negative.
>>> knapsack_space_optimized(1, [1], [1.5], 1)
Traceback (most recent call last):
...
TypeError: Value at index 0 must be an integer.
"""
if num_items < 0:
raise ValueError("The number of items cannot be negative.")
if capacity < 0:
raise ValueError("The knapsack capacity cannot be negative.")
if num_items > len(weights) or num_items > len(values):
raise ValueError("The number of items exceeds the provided input lengths.")
Comment on lines +78 to +83
for item_index in range(num_items):
item_weight = weights[item_index]
item_value = values[item_index]
if not isinstance(item_weight, int):
msg = f"Weight at index {item_index} must be an integer."
raise TypeError(msg)
if item_weight < 0:
msg = f"Weight at index {item_index} cannot be negative."
raise ValueError(msg)
if not isinstance(item_value, int):
msg = f"Value at index {item_index} must be an integer."
raise TypeError(msg)

dp = [0] * (capacity + 1)
for item_index in range(num_items):
item_weight = weights[item_index]
item_value = values[item_index]
for current_capacity in range(capacity, item_weight - 1, -1):
dp[current_capacity] = max(
dp[current_capacity], item_value + dp[current_capacity - item_weight]
)
Comment on lines +98 to +104
return dp[capacity]


def knapsack_with_example_solution(w: int, wt: list, val: list):
"""
Solves the integer weights knapsack problem returns one of
Expand Down
Loading