leetcode 322. 零钱兑换 思考分析
目錄
- 1、題目
- 2、思路分析
- 3、參考鏈接
1、題目
給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。
你可以認為每種硬幣的數量是無限的。
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
2、思路分析
這一題和leetcode 39. 組合總和 思考分析有點像,不過要求不同。
39題要求的是所有解的集合,而這一題求的是最優解。
所以直接套用39回溯思路,然后從子解中找到最小的即可,貌似也是能做的,不過會超時。。。
其實這一題是一道動態規劃題:
如果想求amount = 11時的最少硬幣數(原問題),如果知道amout =10的最少硬幣數(子問題),你只需要把子問題的答案加一(再選一枚1元的硬幣),因為硬幣的數量是沒有限制的,當然也可能是amout =6的最少硬幣數加上一個面額為5的硬幣。這時候就需要取最少的硬幣數了。
子問題之間是相互獨立的。
1、分析最優子結構:
湊成面值為 11 的最少硬幣個數可以由以下三者的最小值得到:
湊成面值為 10 的最少硬幣個數 + 面值為 1 的這一枚硬幣;
湊成面值為 9 的最少硬幣個數 + 面值為 2 的這一枚硬幣;
湊成面值為 6 的最少硬幣個數 + 面值為 5 的這一枚硬幣。
dp[11] = min (dp[10] + 1, dp[9] + 1, dp[6] + 1)
2、確定【DP狀態】
dp[i] :湊齊總價值 i 需要的最少硬幣個數;
3、確定狀態轉移方程
需要注意的地方:
單枚硬幣的面值首先要小于等于 當前要湊出來的面值。
時間復雜度:O(N \times amount)O(N×amount),這里 NN 是可選硬幣的種類數,amountamount 是題目輸入的面值;
空間復雜度:O(amount)O(amount),狀態數組的大小為 amountamount。
由于dp數組是自底向上求解的,所以過程中不會出現重疊子問題
需要注意的地方:
1、數組初始化把初值amount+1換成Integer.MAX_VALUE為什么就不行了 ?
如果初值賦值為正無窮,dp[i - coin] +1 可能會發生整型溢出。
2、循環的判斷條件if (i - coin >= 0 && dp[i - coin] != amount + 1)為什么要判斷 dp[i - coin] != amount + 1呢
amount + 1 在這里表示的是當前狀態表示的金額不能被候選硬幣的和表示。
去掉dp[i-coin] != amount + 1 這個判斷條件也是可以的, 因為若是 dp[i-coin] = amount + 1, 在下一步 dp[i] = Math.min(dp[i], 1 + dp[i - coin]) 也會將amount+1+1這個值過濾掉的,即amount + 1仍然是無效的。 因為數組中的有效值不會超過amount+1,就算有1塊錢的硬幣,最大值也就是amount,因此在取兩個數的最小值時已經自動將amount+1這個值過濾掉了。
3、參考鏈接
動態規劃、完全背包、BFS(包含完全背包問題公式推導)
labuladong的公眾號文章
總結
以上是生活随笔為你收集整理的leetcode 322. 零钱兑换 思考分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C++grammar】文件系统以及pa
- 下一篇: 弹药在PKC怎么把血量堆到32W以上啊?