1. 程式人生 > >最少貨幣數問題

最少貨幣數問題

題目:

給定陣列arr, arr中所有的值都為正數且不重複。每個值代表一中面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求組成aim的最少貨幣數。

思路 :

採用動態規劃的思想來解此題。首先設定dp[i][j]陣列,i的意思是當前的最大貨幣數,j的意思是目標貨幣數。因此dp[i][j]的意思就是使用最大貨幣i可以組成貨幣j的最少貨幣數。假設現在有{10,5,2,1}的貨幣,要求找出15元。當手裡有1元時,無法找出15元,但是當最大的貨幣數為5元時,可以有5+5+5這一種情況,貨幣數最少為3.
設此時的dp[i][j]為MaxValue(Integer所能表示的最大值)。依次遍歷每一種貨幣值和目標錢數。其中有一個重要的公式:

dp[i][j] = min{dp[i-1][j],dp[i][j-amount]+1};

即當前手裡的貨幣值最大的為i時,目標金額減去i的數值amount,計算最大為i求定額j-amount的數目。該值之前曾計算出來。注意需要在最終解上+1。同時還要和i-1情況下的貨幣值(也可以組成目標j的貨幣值)做一個對比,取最小值。

解題程式碼:

public int Solution(int [] coins,int aim){
        if(coins == null || aim<=0)
            return 0;
        //動態規劃陣列
        int
[][] dp = new int [coins.length][aim+1]; int maxvalue = Integer.MAX_VALUE; //初始化dp陣列 for(int i=1;i<=aim;i++){ dp[0][i] = maxvalue; if(i>=coins[0] && dp[0][i-coins[0]] != maxvalue){ dp[0][i] = dp[0][i-coins[0]]+1; } } //計算每個陣列所需的最小貨幣數
int left = 0; for(int i=1;i<coins.length;i++){ for(int j=1;j<aim+1;j++){ left = maxvalue; if(j>=coins[i]&& dp[i][j-coins[i]] != maxvalue){ left = dp[i][j-coins[i]]+1; } dp[i][j] = left<dp[i-1][j]?left:dp[i-1][j]; } } return dp[coins.length-1][aim]; }