硬幣找零,即數字和為sum的幾種問題
問題一
1.問題描述
假設有幾種硬幣,如1、3、5,並且數量無限。請找出能夠組成某個數目的找零所使用最少的硬幣數。
2.問題分析
動態規劃的思想,用 dp[] 存放自底向上問題的解。dp[] 大小為 amount,dp[k] = min(dp[k - coin[i]) + 1
3.Java實現
public int coinChange(int[] coins, int amount) {
int max = amount + 1;
int[] dp = new int[amount + 1];
//先令 dp[] 初始化為 amount + 1
Arrays.fill(dp, max);
//當 amount = 0 時,解也是 0
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
//如果 dp[amount] > amount,即還是初始化的值,說明無解
return dp[amount] > amount ? -1 : dp[amount];
}
問題二
1.問題描述
將上題中的求最小的硬幣數,改成所有的方案。即,假設有幾種硬幣,並且數量無限。請找出能夠組成某個數目的找零所有的方案數。
2.問題分析
用 dp[i, j] 表示:使用 第 1,2,…i 種面值的硬幣時,需要找金額為 j 的錢,最多可採用多少種不同的方式。
i 表示可用的硬幣種類數, j 表示 需要找回的零錢
有兩種情況:對於某種面值的硬幣,要麼使用了它,dp[i, j - coins[i]]
要麼不使用它,dp[i - 1, j]
所以,dp[i, j] = dp[i, j - coins[i]] + dp[i - 1, j]
3.Java實現
public int coinChangeWays(int[] coins, int n){
int m = coins.length;
int[][] dp = new int[m+1][n+1];
//第一列 dp[i][0] 表示用coins[i]組成面額為0的錢的方案,即不需要任何貨幣,初始化為1
for(int i = 0; i <= m; i++)
dp[i][0] = 1;
//第一行 dp[0][j] 沒有貨幣,初始化為0
for(int i = 1; i <= n; i++)
dp[0][i] = 0;
for(int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++){
if (j - coins[i] >= 0)
dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]];
else
dp[i][j] = dp[i - 1][j];
}
}
return dp[m][n];
}
問題三
1.問題描述
將上題中硬幣無限量使用,改為每個面值只有一個硬幣。即,假設有幾種硬幣,每種硬幣只有一個。請找出能夠組成某個數目的找零所有的方案數。
題目還可以這樣,同一個意思:
給定一個有n個正整數的陣列A和一個整數sum,求選擇陣列A中部分數字和為sum的方案數。
當兩種選取方案有一個數字的下標不一樣,我們就認為是不同的組成方案。
2.問題分析
也是兩種方法:要麼加這個數,dp[i - 1, j - weight[i]]。和上題不同的只是,加上這個數,i 也要減一。
要不不加這個數,dp[i - 1, j]
所以,dp[i, j] = dp[i-1, j] + dp[i-1, j-weight[i]]
3.Java實現
public int sunWays(int[] weight, int sum) {
int n = weight.length;
int[][] dp = new int[n+1][sum+1];
for (int i = 0 ; i < n ;i++) {
dp[i][0] = 1;
}
for (int j = 1 ; j < sum ;j++) {
dp[0][j] = 0;
}
for (int i = 1 ; i <= n ;i++) {
for (int j = 0 ; j <= sum ;j++) {
if(weight[i] <= j)
dp[i][j] = dp[i-1][j] + dp[i-1][j-weight[i]];
else
dp[i][j] = dp[i-1][j];
}
}
return dp[n][sum];
}
上面的方法,dp[][]用了二維陣列, 也可以用一維陣列來節省空間。
public int sumWays(int[] weight, int sum){
int dp[]=new int[sum+1];
dp[0]=1;
for(int i = 0; i < weight.length; i++){
for(int j = sum; j >= weight[i]; j--){
dp[j] = dp[j - weight[i]] + dp[j];
}
}
return dp[sum];
}
相關推薦
硬幣找零,即數字和為sum的幾種問題
問題一 1.問題描述 假設有幾種硬幣,如1、3、5,並且數量無限。請找出能夠組成某個數目的找零所使用最少的硬幣數。 2.問題分析 動態規劃的思想,用 dp[] 存放自底向上問題的解。dp[] 大小為 amount,dp[k] = min
硬幣找零,最長上升子序列,揹包問題等動態規劃問題詳解
1.硬幣找零 如果我們有面值為 1 元、3 元和 5 元的硬幣若干枚,如何用最少的硬幣湊夠 11 元? 首先我們思考一個問題,如何用最少的硬幣湊夠 i 元(i<11)?為什麼要這麼問呢? 兩個原因:1.當我們遇到一個大問題時,總是習慣把問題的規模變小,這樣便於分析討論。 2.這
滴滴出行 數字和為sum的方法數(dp)
給定一個有n個正整數的陣列A和一個整數sum,求選擇陣列A中部分數字和為sum的方案數。 當兩種選取方案有一個數字的下標不一樣,我們就認為是不同的組成方案。 輸入描述: 輸入為兩行: 第一行為兩個正整數n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000
滴滴出行 數字和為sum的方法數(dp)
給定一個有n個正整數的陣列A和一個整數sum,求選擇陣列A中部分數字和為sum的方案數。 當兩種選取方案有一個數字的下標不一樣,我們就認為是不同的組成方案。 輸入描述: 輸入為兩行: 第一行為兩個正整數n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000) 第二行為n個正
sincerit 數字和為sum的方法數(01揹包問題)
題目描述 給定一個有n個正整數的陣列A和一個整數sum,求選擇陣列A中部分數字和為sum的方案數。 當兩種選取方案有一個數字的下標不一樣,我們就認為是不同的組成方案。 輸入描述: 輸入為兩行: 第一行為兩個正整數n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000) 第二行為
iOS判斷字串中包含數字和字母的幾種情況
//直接呼叫這個方法就行 -(int)checkIsHaveNumAndLetter:(NSString*)password{ //數字條件 NSRegularExpression *tNum
斐波那契數列和階乘的尾函式優化,動態規劃解決最小硬幣找零和揹包問題
// 遞迴是一種解決問題的方法,它解決問題的各個小部分,直到解決最初的大問題。遞迴通常涉及函式呼叫自身 // 斐波那契數列尾呼叫優化 function fibonacci(n, acc1 = 1, acc2 = 1) { if (n === 1 || n === 2) { ret
C#練習 找零,人民幣有100元、50元、10元、5元、2元和1元六種,最少需要準備多少張人民幣
Console.WriteLine("輸入工資"); int money = Convert.ToInt32(Console.ReadLine()); i
[LeetCode] Coin Change 2 硬幣找零之二
lee diff bit inf may tco nom not leet You are given coins of different denominations and a total amount of money. Write a function t
codevs 3961 硬幣找零【完全背包DP/記憶化搜索】
得到 可能 代碼 好的 default ++ -h 數值 rip 題目描述 Description 在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。
動態規劃——硬幣找零
max 關系 i++ 是否 coin fine 個數 names std 動態規劃問題,主要在於需要想清楚遞推關系,num[i][j]表示能使用 i 種硬幣時,得到 j 零錢的最優解。 想來就是首先假設只能使用第一種硬幣 1 ,那麽會得到num[ 1 : n] =
leetcode 518. Coin Change 2/硬幣找零 2
sign script 我們 have fun 數量 -c pub NPU 歸納於http://www.cnblogs.com/grandyang/p/7669088.html 原題https://leetcode.com/problems/coin-change-2/de
動態規劃-硬幣找零問題四種情況
題目1:給定陣列arr,arr中所有的值都是正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求組成aim的最少貨幣數。 舉例: arr[5,2,3],aim=20。 4張5元可以組成20元,其他的找錢方案都要使
劍指offer——找出二叉樹和為n的路徑
連結串列和二叉樹比較難做,主要因其均以鏈相連線,.next and .left 來輸出結構中的資料,無法精確定位,所以通常用遞迴方法實現。 通過遞迴方法,本人感覺最重要的是確定.next的這部中具體實現的操作,然後逐漸實現遞迴。找出二叉樹和為n的路徑,就針對每一步做加和操作以及記錄路徑,並判
輸入一個正整數n,輸出所有和為n的連續正整數序列
1 public static void main(String[] args) { 2 Scanner sc = new Scanner(System.in); 3 while (true) { 4 System.out.prin
sincerit 硬幣找零之種類數
現存在一堆面值為 1,2,5,10,20,50 面值的硬幣,問給你一個紙幣是m,求出把m紙幣換成硬幣的種類數 思路是動態規劃 假設有n種硬幣,紙幣是m dp[i][j] 表示前i種硬幣能把紙幣換成硬幣的種類數 轉移方程 對於第i種硬幣 dp[i][j] = dp[i-1][j] + dp[i
sincerit 硬幣找零之最小數量
現存在一堆面值為 1,2,5,10,20,50 面值的硬幣,問找出總值為 N個單位的零錢的所使用的硬幣的數量最少,輸出最小值 #include <iostream> using namespace std; int values[100]; //硬幣面值的陣列 int mai
和為S的兩個數字/和為S的連續正數序列
1.和為S的兩個數字,牛客網ac 其實同leetcode第一題兩數之和一樣, 雙指標,從兩邊逼近。 class Solution { public: vector<int> FindNumbersWithSum(vector<int>
牛客國慶集訓派對Day4——G 區間權值(找規律,雙重字首和)
題目大意: 小 Bo 有 n 個正整數 a1..an,以及一個權值序列 w1…wn,現在他定義 現在他想知道 的值,需要你來幫幫他。你只需要輸出答案對 109+7 取模
leetcode-322 硬幣找零問題
我的版本: int coinChange(vector<int>& coins, int amount) { if(coins.size()==0){return -1;} int *dp=new int[amount+1]; for(