異なる金種
coins
と合計金額のコインが与えられamount
ます。合計金額を構成するために必要なコインの最小数を計算する関数を記述します。コインの組み合わせで合計金額を構成できない場合は、を返し-1
ます。
最適な下部構造に合わせて兌換性を変更します。たとえば、amount = 11
(元の質問)の場合に最小コイン数を見つけたい場合、Couchuのamount = 10
最小コイン数(サブ問題)がわかっている場合、答えは追加するだけです。サブ問題(額面1のコインの再選)が元の質問に対する答えです。コインの数に制限がないため、サブ質問間の相互制限はなく、互いに独立しています。
正しい状態遷移方程式をリストする方法は?
まず第一に、私達は私達の目的を明確にしなければなりません:目標額を形成するために最小のコインを使用してください
-
ベースケースを決定する
これは非常に単純で、
amount
コインが目標金額をCouchuしていないため、アルゴリズムの目標金額は0:00を返すようです。 -
「状態」を決定します。これは、元の問題とサブ問題で変化する変数です。
コインの数は無制限であるため、コインの額面も対象によって与えられ、目標量のみがベースケースに近づき続け
amount
ます。したがって、唯一の「状態」は目標量です。 -
「選択」、つまり「状態」を変化させる動作を決定します。
なぜ目標額が変わるのですか?コインを選んでいるので、選んだコインは目標額を減らすのと同じです。したがって、すべてのコインの額面はあなたの「選択」です。
-
関数/配列の定義を明確にします。
dp
ここでは、ボトムアップアプローチを使用して、1つのステップで直接、配列
dp[amount]
は、amount
必要なときに最小数のコインの量(つまり、最終的な解決策)のターゲットを表します。状態遷移方程式は次のとおりです。
dp(n)= {0、n = 0 − 1、n <0 min {dp(n −コイン)+ 1∣coin∈coins}、n> 0 dp(n)= \ begin {cases} 0、\ quad n = 0 \\-1、\ quad n <0 \\ min \ {dp(n-coin)+ 1 \ quad | \ quad coin \ in coins \}、\ quad n> 0 \ end {cases}d p (n )=⎩⎪⎨⎪⎧0 、n=0− 1 、n<0m i n { d p (n−c o i n )+1∣C O I N∈c o i n s } 、n>>0
dp(n)
定義:目標金額を入力します。n
目標金額Couchun
は最小コイン数を返します。
PS:dp
配列が初期化さamount + 1
れる理由amount
、コインの数が最大量に等しい可能性があるためamount
(コインの額面で1元あたり)、初期化はamount + 1
正の無限大に初期化され、その後の最小値を容易にするために構成されます値。
import java.util.*;
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount+1];
Arrays.fill(dp, amount+1);
dp[0] = 0;
for(int i = 0; i <= amount; i++){
for(int coin:coins){
if(i-coin >= 0){
dp[i] = Math.min(dp[i-coin]+1, dp[i]);
}
}
}
return (dp[amount] == amount+1) ? -1 : dp[amount];
}
}
時間計算量:
O(kN)
、k
コインの種類の数スペースの複雑さ:
O(N)