518. Coin Change II
題目網址:https://leetcode.cn/problems/coin-change-ii/
題意:給一整數 array
coins
表示不同面額的硬幣, 和一整數amount
表示總金額。返回可以湊成
amount
的硬幣組合數。如果任何硬幣組合都無法湊出總金額, 則返回0
。假設每一種面額的硬幣有無限個。
題目保證結果符合 32-bit 有號整數。
Solution 1:
想法:利用 DP
1. 定義狀態:
- 首先, 會在
coins
前先加上一個0
, 代表什麼元素都沒有的狀態dp[i][j]
:前i
種硬幣湊齊金額j
的組合數2. 得到轉移方程:
coins[i]
有「選 or 不選」兩種可能:
rods[i]
不選, 則dp[i][j] = dp[i - 1][j]
rods[i]
要選, 則dp[i][j] = dp[i][j - coins[i]]
(每一種面額可無限取, 故為i
而非i - 1
)3. 初始化:
dp[0][0]
:當沒有任何硬幣時, 湊齊金額0
的組合數為1
(什麼都不選也是一種方案)
➔dp[0][0] = 1
dp[i][0]
:當amount = 0
時, 前i
種硬幣湊齊金額j
的組合數為1
(什麼都不選也是一種方案), 其中1 ≤ i ≤ n
➔dp[i][0] = 1
dp[0][j]
:當沒有任何硬幣時, 湊齊金額j
的組合數為0
, 其中1 ≤ j ≤ amount
➔dp[0][j] = 0
class Solution { |
- time:$O(n \cdot amount)$ ➔ for loop, 其中
n
是硬幣種類 - space:$O(n \cdot amount)$ ➔
dp
Solution 2:
想法:改進 Solution 1, 因為
dp[i][j]
只會用到上一列的狀態, 故只需記住上一列的狀態即可
class Solution { |
- time:$O(n \cdot amount)$ ➔ for loop, 其中
n
是硬幣種類 - space:$O(amount)$ ➔
dp
,prevRow
延伸問題:
for loop 內、外層能否對調?
不能, 因為這裡定義的 subproblem 是「選擇第
i
種硬幣時, 湊齊金額j
的方案(組合數)」。如果對調了, 則 subproblem 就會變成「對於金額j
, 選擇硬幣的方案(排列數)」e.g.
amount = 3
,coins = [1, 2]
- 內、外層對調後, 會有 1 + 2、2 + 1 這兩種方案
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Zako's Blog!
評論