ダイナミックプランニング:小銭両替の問題(javascriptの解)
14002 ワード
前言
昨日の面接の时に突然动态计画に言及して、结局面接官は私に动态计画は何ですかと闻いて、私は意外にも一时的に表现することができなくて、ここで自分の话で缲り返し练习してみます:动态计画は先に大きい问题の子の问题を探し当てて、子の问题の解を中间の结果として最终の问题を解いて、しかも子の问题の解は局部が最も良いです.
動的計画問題の一般的な解題手順
小銭両替
タイトルの説明
異なる額面のコインcoinsと総金額amountを与えます.合計金額にまとめるのに必要な最小限のコイン数を計算する関数を作成します.合計金額を構成できるコインの組み合わせがない場合は、-1を返します.
コインの数は無限だと思います.
例1:
入力:coins=[1,2,5],amount=11出力:3解釈:11=5+5+1
考え方:
jsコード
var coinChange = function (coins, amount) {
//
let dp = new Array(amount + 1).fill(Infinity)
dp[0] = 0
console.log(dp);
let len = coins.length;
for (let i = 0; i <= amount; i++) {
for (let j = 0; j < len; j++) {
// :
//
if (i >= coins[j] && dp[i - coins[j]] !== Infinity) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1)
}
}
}
if (dp[amount] === Infinity) {
return -1;
}
return dp[amount];
};
console.log(coinChange([1, 2, 5], 11));
小銭両替II
タイトルの説明
異なる額面のコインと総額を指定します.関数を書き出して総額にまとめることができるコインの組み合わせ数を計算します.各額面のコインに無限があると仮定します.
例1:
入力:amount=5,coins=[1,2,5]出力:4解釈:合計金額にまとめるには4つの方法がある:5=5=2+2+15=2+1+15=1+1+1+1+1+1
構想
実はこの問題と階段の調整は実は同じタイプの問題です.
完全なリュックサックの組み合わせの問題--容量amountを満たすリュックサックは、いくつかのコインの組み合わせがあります
他の人の考えを見て、最初はこのように書いたコードです.
var change = function (amount, coins) {
// dp[i] i
let dp = new Array(amount + 1).fill(0);
dp[0] = 1
for (let i = 1; i <= amount; i++) {
for (let j = 0; j < coins.length; j++) {
dp[i] = dp[i - coins[j]] + dp[i]
}
}
return dp[amount];
};
console.log(change(5, [1, 2, 5]))
そしてずっと間違っていて、結果は真実の答えより大きくて、それから私はdebugerの後でこれが求めた配列数の結果であることを知っていて、答えは組み合わせ数を求めて、そして私はleetcodeで次の文をひっくり返しました
組み合わせ数を求めると外層forが物を巡り、内層forがリュックサックを巡る.配列数を求めると外層forがリュックサックを巡り、内層forが物を巡ります.
だから遍歴の順番を変えて
var change = function (amount, coins) {
// dp[i] i
let dp = new Array(amount + 1).fill(0);
dp[0] = 1
for (let i = 0; i < coins.length; i++) {
for (let j = coins[i]; j <= amount; j++) {
dp[j] = dp[j] + dp[j - coins[i]]
}
}
return dp[amount];
};
console.log(change(5, [1, 2, 5]))