動(dòng)態(tài)規(guī)劃(持續(xù)更新)

知乎一篇高贊動(dòng)態(tài)規(guī)劃
《labuladong的算法小抄-動(dòng)態(tài)規(guī)劃章節(jié)》


動(dòng)態(tài)規(guī)劃應(yīng)用比較多的情況是求最值。核心問題是窮舉。
首先動(dòng)態(tài)規(guī)劃三要素
1.記憶數(shù)組/重疊子問題。
2.最優(yōu)子結(jié)構(gòu)。
3.狀態(tài)轉(zhuǎn)移方程。

對(duì)于記憶數(shù)組,我想說的是,最傳統(tǒng)的遞歸暴力解法會(huì)有很多的重復(fù)計(jì)算,最終的結(jié)果以來歷史計(jì)算的結(jié)果,那動(dòng)態(tài)規(guī)劃就可以減少重復(fù)計(jì)算。

最優(yōu)子結(jié)構(gòu):首先要符合最優(yōu)子結(jié)構(gòu),子問題必須相互獨(dú)立。例如我們接下來的每個(gè)例題都會(huì)分析是否能用動(dòng)態(tài)規(guī)劃來做,在湊零錢問題中,硬幣數(shù)量沒有限制,任何子問題都沒有限制,互相獨(dú)立。分享一個(gè)例子:你參加考試,你的原問題是考出最高的總成績(jī),那么你的子問題就是把各科成績(jī)都考到最高分,各科最高分那你的每道題都是最高分。。。。最終結(jié)果就是滿分。那這個(gè)問題符合最優(yōu)子結(jié)構(gòu),每門課程考到最高分,這些子問題互相獨(dú)立、互不干擾。但如果有個(gè)條件,你的語文數(shù)學(xué)成績(jī)相互制約,數(shù)學(xué)成績(jī)高,就會(huì)語文低,那就會(huì)子問題不獨(dú)立,各科無法同時(shí)達(dá)到最優(yōu)解。

做題步驟
1.定義數(shù)組(很重要),dp[i]含義。
2.找出數(shù)組元素關(guān)系式,這里我分享自己的思路就是,一般都是第n個(gè)結(jié)果是什么,那第n個(gè)結(jié)果之前的結(jié)果是什么,這往往是我做題中的破題之處。例如:斐波那契數(shù)列,dp[n] = dp[n-1] + dp[n-2];矩陣從左上角到右下角,求最大值,那到右下角前會(huì)經(jīng)過哪里?;湊零錢問題,在得到最少的硬幣個(gè)數(shù)dp[n]之前,得到dp[n]= min(dp[n-coin]+1 ,dp[n]);coin表示硬幣面值,n表示需要湊的金額。
3.base case最簡(jiǎn)單案例,初始化。


1 湊零錢問題

給你一個(gè)整數(shù)數(shù)組 coins ,表示不同面額的硬幣;以及一個(gè)整數(shù) amount ,表示總金額。
計(jì)算并返回可以湊成總金額所需的 最少的硬幣個(gè)數(shù) 。如果沒有任何一種硬幣組合能組成總金額,返回 -1 。

你可以認(rèn)為每種硬幣的數(shù)量是無限的。
示例 1:
輸入:coins = [1, 2, 5], amount = 11
輸出:3
解釋:11 = 5 + 5 + 1
示例 2:
輸入:coins = [2], amount = 3
輸出:-1
示例 3:
輸入:coins = [1], amount = 0
輸出:0
示例 4:
輸入:coins = [1], amount = 1
輸出:1
示例 5:
輸入:coins = [1], amount = 2
輸出:2

class Solution {
    public int coinChange(int[] coins, int amount) {
        //定義數(shù)組,amount == i 的時(shí)候最少的硬幣數(shù)量
        int[] dp = new int[amount+1];
        //初始化
        for(int i = 0; i < amount+1; i++){
            dp[i] = amount+1;
            //最差的結(jié)果就是無數(shù)個(gè)1相加,那amount+1相當(dāng)于無窮大。
            //代表-1,表示無解
        }
        dp[0] = 0;
        //開始循環(huán)
        for(int i = 1; i < amount+1; i++){
            for(int j = 0; j < coins.length; j++){
                if(i - coins[j] < 0) continue;
                dp[i] = Math.min(dp[i], 1 + dp[i-coins[j]]);
            }
        }
        return (dp[amount] == amount+1)?-1: dp[amount];
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容