這道題相似於徹底揹包問題,每一個物品均可以無限使用,可是要求揹包必須裝滿,並且要求揹包中的物品數目最少, 概括爲數學問題就是,數組
public int coinChange(int[] coins, int amount) { if(coins.length == 0) return -1; //聲明一個amount+1長度的數組dp,表明各個價值的錢包,第0個錢包能夠容納的總價值爲0,其它所有初始化爲無窮大 //dp[j]表明當錢包的總價值爲j時,所須要的最少硬幣的個數 int[] dp = new int[amount+1]; Arrays.fill(dp,1,dp.length,Integer.MAX_VALUE); //i表明可使用的硬幣索引,i=2表明只在第0個,第1個,第2個這三個硬幣中選擇硬幣 for (int i = 0; i < coins.length; i++) { /** * 當外層循環執行一次之後,說明在只使用前i-1個硬幣的狀況下,各個錢包的最少硬幣個數已經獲得, * 有些錢包的值仍是無窮大,說明在僅使用前i-1個硬幣的狀況下,不能湊出錢包的價值 * 如今開始再放入第i個硬幣,要想放如w[i],錢包的價值必須知足j>=w[i],因此在開始放入第i個硬幣時,j從w[i]開始 */ for (int j = coins[i]; j <= amount; j++) { /** * 若是錢包當前的價值j僅能容許放入一個w[i],那麼就要進行權衡,以得到更少的硬幣數 * 若是放入0個:此時錢包裏面硬幣的個數保持不變: v0=dp[j] * 若是放入1個:此時錢包裏面硬幣的個數爲: v1=dp[j-coins[i]]+1 * 【前提是dp[j-coins[i]]必須有值,若是dp[j-coins[i]]是無窮大,說明沒法湊出j-coins[i]價值的錢包, * 那麼把w[i]放進去之後,天然也湊不出dp[j]的錢包】 * 因此,此時當錢包價值爲j時,裏面的硬幣數目爲 dp[j]=min{v0,v1} * 若是錢包當前價值j可以放入2個w[i],就要再進行一次權衡 * 若是不放人第2個w[i],此時錢包裏面硬幣數目爲,v1=dp[j]=min{v0,v1} * 若是放入第2個w[i], 此時錢包裏面硬幣數目爲,v2=dp[j-coins[i]]+1 * 因此,當錢包的價值爲j時,裏面的硬幣數目爲dp[j]=min{v1,v2}=min{v0,v1,v2} * 錢包價值j能容許放入3個,4個.........w[i],不斷更新dp[j],最後獲得在僅使用前i個硬幣的時候,每一個錢包裏的最少硬幣數目 */ if(dp[j-coins[i]] != Integer.MAX_VALUE) { dp[j] = Math.min(dp[j], dp[j-coins[i]]+1); } } } if(dp[amount] != Integer.MAX_VALUE) return dp[amount]; return -1; }