LeetCode - Coin Change(找零)
題目描述
給定一個整數數組 coins
,其中每個元素代表一種硬幣的面值,以及一個整數 amount
,表示總金額。請找出可以用硬幣湊出這個總金額所需的最少硬幣數。如果無法湊出該金額,則返回 -1
。
你可以認為每種硬幣的數量是無限的。
範例:
1
2
3
4
5
6
7
8
9
輸入:coins = [1, 2, 5], amount = 11
輸出:3
解釋:11 = 5 + 5 + 1,所以最少需要 3 枚硬幣。
輸入:coins = [2], amount = 3
輸出:-1
輸入:coins = [1], amount = 0
輸出:0
限制:
1 <= coins.length <= 12
1 <= coins[i] <= 2^31 - 1
0 <= amount <= 10^4
解法思路
這是一道典型的「最小硬幣找零」問題,可以使用動態規劃來解決。構建一個數組 dp
,其中 dp[i]
表示湊出金額 i
所需的最少硬幣數。
動態規劃步驟
- 初始化:建立一個長度為
amount + 1
的數組dp
,初始值為inf
(代表無法達到的金額),其中dp[0] = 0
,表示金額為 0 時不需要硬幣。 - 遞推公式:對於每個金額
i
,遍歷每一種硬幣面值coin
,若i - coin >= 0
,則更新dp[i] = min(dp[i], dp[i - coin] + 1)
,表示用coin
這枚硬幣可以達成的最少硬幣數。 - 結果:最終,若
dp[amount]
仍然是初始值,則返回-1
;否則,返回dp[amount]
的值。
代碼實現
以下是 Python 的實現:
1
2
3
4
5
6
7
8
9
10
def coinChange(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
代碼解析
- 初始化
dp
數組:設置長度為amount + 1
的數組dp
,並初始化為無窮大,dp[0]
為 0。 - 更新
dp
:對於每個金額i
,檢查用每種硬幣coin
是否可以減少所需硬幣數。 - 返回結果:若
dp[amount]
無法更新,則說明無法湊出該金額,返回-1
;否則返回dp[amount]
。
時間和空間複雜度
- 時間複雜度:O(amount * n),其中
n
是硬幣種類數。對於每一個金額,都遍歷coins
。 - 空間複雜度:O(amount),使用了
dp
數組儲存子問題的解。
本文章以 CC BY 4.0 授權