最少貨幣數問題
阿新 • • 發佈:2019-01-24
題目:
給定陣列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];
}