ソリューション:
これは、動的プログラミング問題は、一般的に最も価値のために使用されるダイナミックプログラミングです。
三つの要素をプログラミングするダイナミック:
ステータス:現在の数の値が
状態遷移方程式:コインの電流量Couchuの電流量がNである、少なくともDP [n]は、
最適な下部構造:現在の値n = 0の場合、0を返す; Nの電流量であれば<0 -1;
暴力再帰:(トップダウン)
再帰終了条件:
- N = 0の電流量は、その後、0を返す場合、N <0、-1の電流量があれば、
コインに再帰的プロセスを詳細= [1,2,5]を、実施例11の量;
N-11 =、N- = 10 1;
N- = 10、N - = 9 1;
...
と、それは再帰的にまでなっている
、N = 1、N - = 1 0;
RETURN 0、RES = 1;
および
N- = 1、2 = N- -1
- ----、N = -4 -5
ここで、n = 1サイクルの終了のために、即ち戻りRES = 1;この場合の計算DP [1]最適解;
バック
場合、N = 2、N - 1 = 1再帰戻り、
ケースRES = 2;
および
N = 2、N - 2 = 0; 戻り0、RES =分(2、1)= 1、
N-2 =、= N - 5 -3。 -1
このとき、サイクルの終わりには、リターンRES = 1;最適のこの時間DP [2]で算出溶液;及び
前後戻りN = 3への復帰は、この方法によれば。
コードは以下の通りであります:
class Solution:
def coinChange(self, coins, amount):
def dfs(n):
##递归终止条件
if n == 0:
return 0
if n < 0:
return -1
res = float("inf")
for i in range(len(coins)):
sub_problem = dfs(n - coins[i])
#子问题无解,跳过
if sub_problem == -1:
continue
#res记录子问题的最优解
res = min(res, 1 + sub_problem)
if res == float("inf"):
return -1
else:
return res
return dfs(amount)
しかし、これらの方法では、冗長な計算を紹介します。
以下のように:
メモアルゴリズム:
ダブルカウントを避けるために、すでに辞書のレコードで計算した値を確立します。
class Solution:
def coinChange(self, coins, amount):
memo = dict()
#备忘录算法
def dfs(n):
if n in memo:return memo[n]
if n == 0:
return 0
if n < 0:
return -1
res = float("inf")
for coin in coins:
sub_problem = dfs(n - coin)
#子问题无解,跳过
if sub_problem == -1:
continue
#res记录子问题的最优解
res = min(res, 1 + sub_problem)
if res == float("inf"):
return -1
else:
memo[n] = res
return res
return dfs(amount)
ボトムアップアルゴリズム:
問題分解:
leetcodeから基準の公式解釈:
個人が理解:
私は、必要が各コインを通過する電流量、I-コインが最小値に達し、2、コイン= 1の合計量、2]例として、
F(2)=分(F(2-1)、F(2-2))= + 1の1。
以下のコード、2サイクルを達成するために、トラバース周期の量の第一の層を得ること各量の硬貨の最適数、
各コインを通過しながら、第二層は、コインの最小必要数の電流量を見つける;しかしサイクルを行う前に、必要性が現在のサイズとコインの量との関係を決定するために、コインの量より少ないが存在することになります場合、負の数。
class Solution:
def coinChange(self, coins, amount):
dp = [amount + 1]*(amount + 1)
dp[0] = 0
for i in range(1,amount + 1):
for j in range(len(coins)):
if i >= coins[j]:
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
if dp[amount] == amount + 1:
return -1
else:
return dp[amount]
このコードと一致する考え方にコードが、逆サイクルである。
このコードは、次のは、現在のコイン、DP [I]の値にDPに決定され、この場合、硬貨の完全なサイクル後、得られました[ i]は最適ではないが、最適値DPを得るために、硬貨の各々を横断するプロセスにおける[I];及び
例えば、2の量、] 1,2 [のコインであり、
硬貨は1であり、DP [1] =分(DP [ 1]、DP [0] + 1)= 1、DP [2] =分(DP [2]、DP [2-1] + 1)= 2、
コインがある場合、 ___________________________ DP [2] =分( DP [2]、DP [2-2] + 1)= 1
と同時に、コード・サイクルと電流量以下の第二層(コインサイズなしで決定される現在のコインからのものであるのでサイクルを開始した量の大きさ)は、量がサイクルを開始するために、1からのものであるので、コードで一方、決意を必要とするので、二度目は、第複雑さと高効率未満です。
class Solution:
def coinChange(self, coins, amount):
dp = [amount + 1]*(amount + 1)
dp[0] = 0
for i in range(len(coins)):
for j in range(coins[i], amount + 1):#避免了用if条件语句
dp[j] = min(dp[j], dp[j - coins[i]] + 1)
if dp[amount] == amount + 1:
return -1
else:
return dp[amount]