Optimal Bottom-Up Dynamic Programming Approach:
- Build up solutions from 0 to amount where dp[i] represents the minimum coins needed for amount i.
def coin_change(coins: list[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for x in range(coin, amount + 1):
dp[x] = min(dp[x], dp[x - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
Complexity & Key Logic:
- Time Complexity: O(amount * len(coins)) dual-loop iterations.
- Space Complexity: O(amount) array storing subproblem solutions.
- Algorithm Details:
- Base case: 0 amount requires 0 coins (dp[0] = 0). Initialize remaining cells to infinity.
- Transition: For each coin, if x >= coin, dp[x] = min(dp[x], dp[x - coin] + 1).
- If dp[amount] remains infinity at completion, amount cannot be formed; return -1.