Leetcode Note: Coin Change
I. Description
You are given coins of different denominations and a total amount of money amount. write a function to compute the fewest number of coins that you need to make up that amount. if that amount of money cannot be made up by any combination of the coins, return-1.
Example 1:
coins = [1, 2, 5],amount = 11
Return3 (11 = 5 + 5 + 1)
Example 2:
coins = [2],amount = 3
Return-1.
Note:
You may assume that you have an infinite number of each kind of coin.
Ii. Question Analysis
Given coins of different denominations (values are stored in an arraycoins) And a total amount.amount. Compile a function to calculate the minimum number of coins required for the total amount. If the specified amount cannot be collected using an existing coin, return-1.
For this question, it is not feasible to use the greedy algorithm, because it may miss the global optimal solution.
This problem can be solved using dynamic planning to build an arraydp[amount + 1]Used to record0 ~ amountUse each numbercoinsThe minimum number of combinations (for each number, the maximum number of combinations cannot exceedamount + 1Therefore, the array can be initializedamount + 1In this way, as long as there is a valid combination of a logo I, you can useminFunction Overwriteamount + 1If the value of this subscript is stillamount + 1, Indicating thatcoinsTo represent I)
Based on the above ideas, you can write the state transition equation:
dp[x + coins] = min(dp[x] + 1, dp[x + coins])
Wheredp[x]Indicates the collected amount.xThe minimum number of coins required,coinsIndicates the available coin face value, incoinsArray traversal.
Note that before Algorithm Execution, set dp [0] to 0.
Discuss provides a more efficient deep search method. The code is relatively complex, as shown in the second section of the Code below.
Iii. Sample Code
// DP, time complexity: O (n * amount) class Solution {public: int coinChange (vector
& Coins, int amount) {if (amount <0) return-1; if (amount = 0) return 0; // The number of coin combinations cannot be greater than amount, therefore, if the element value of a base object is amount + 1, the subscript vector cannot be combined with coins in coins.
Dp (amount + 1, amount + 1); dp [0] = 0; for (int I = 1; I <amount + 1; ++ I) for (int j = 0; j <coins. size (); ++ j) if (coins [j] <= I) dp [I] = min (dp [I], dp [I-coins [j] + 1); return dp [amount]> amount? -1: dp [amount] ;}};
// DFSclass Solution {public: int currBestResult; void solve(const vector
::iterator & begin, const vector
::iterator & end, int amount, int currCount) { // find a solution, update currBestResult if this is better if(amount == 0) { if(currBestResult == -1) currBestResult = currCount; else currBestResult = min(currBestResult, currCount); return; } // use up all coin types, no solution if(begin == end) return; // can't achiveve a solution better than currBestResult, no need to explore more if(currBestResult != -1 && currBestResult <= amount / *begin + currCount) return; int count, currAmount; // start from the largest remaining coin first for (auto it = begin; it != end; ++it) { int coin = *it; // use coin as much as possible, so that we can get a good solution early to save exploration currAmount = amount % coin; count = amount / coin; while(currAmount < amount) { // find solutions to fill currAmount with smaller coins solve(it + 1, end, currAmount, count + currCount); // scale back by one largest coin to extend currAmount to try solve again in the next iteration currAmount += coin; count--; } } } int coinChange(vector
& coins, int amount) { currBestResult = -1; sort (coins.begin(), coins.end(), greater
()); solve(coins.begin(), coins.end(), amount, 0); return currBestResult; }};
Iv. Summary
Classic questions of dynamic planning are worth learning.