算法模式--動態規劃(dynamic programming)

動態規劃是一種將復雜問題分解成更小的相互依賴的子問題來解決的優化技術

關鍵點:創建dp數組

1. 最小路徑和

//給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。
        // 說明:每次只能向下或者向右移動一步。
        // 示例:
        // 輸入:
        // [
        //   [1,3,1],
        //   [1,5,1],
        //   [4,2,1]
        // ]
        // 輸出: 7
        // 解釋: 因為路徑 1→3→1→1→1 的總和最小。
        //難度:中等
//解題思想:拆分成小問題算出到達每個子位置的最小路徑和
        var minPathSum = function (grid) {
            var m = grid.length;
            var n = grid[0].length;
            var dp = Array.from({ length: grid.length }, item => item = []);
            for (var i = 0; i < m; i++) {
                for (var j = 0; j < n; j++) {
                    if (i === 0 && j === 0) {
                        dp[i][j] = grid[i][j]
                    } else if (i === 0 && j !== 0) {
                        dp[i][j] = grid[i][j] + dp[i][j - 1]
                    } else if (i !== 0 && j === 0) {
                        dp[i][j] = grid[i][j] + dp[i - 1][j]
                    } else {
                        dp[i][j] = Math.min(grid[i][j] + dp[i][j - 1], grid[i][j] + dp[i - 1][j])
                    }
                }
            }
            return dp[m - 1][n - 1]
        };

2.打家劫舍

//         你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
        // 給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
        // 示例 1:
        // 輸入: [1,2,3,1]
        // 輸出: 4
        // 解釋: 偷竊 1 號房屋 (金額 = 1) ,然后偷竊 3 號房屋 (金額 = 3)。
        //      偷竊到的最高金額 = 1 + 3 = 4 。
      //難度:中等
      //解題思想: 根據3次以內的情況得到計算方程
        var rob = function (nums) {
            if (nums.length === 0) return 0;
            //dp dynamic programming 動態規劃簡寫
            var dp = [];
            dp[0] = 0;
            dp[1] = nums[0];
            for (var i = 2; i <= nums.length; i++) {
                dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]);
            }
            return dp.pop();
        };

3.乘積最大子序列

 // 給定一個整數數組 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。
        // 示例 1:
        // 輸入: [2,3,-2,4]
        // 輸出: 6
        // 解釋: 子數組 [2,3] 有最大乘積 6。
        // 示例 2:
        // 輸入: [-2,0,-1]
        // 輸出: 0
        // 解釋: 結果不能為 2, 因為 [-2,-1] 不是子數組。
        var maxProduct = function (nums) {
            if (nums.length === 0) return 0;
            //1.設置初始默認最大值,及默認乘積最大值,因為涉及負數最小值,當遇到負數時,最大和最小會互換,所以設置保存最小乘積變量.
            let max = nums[0], imax = 1, imin = 1;
            for (let i = 0; i < nums.length; i++) {
                if (nums[i] < 0) [imax, imin] = [imin, imax];
                imax = Math.max(imax * nums[i], nums[i]);
                imin = Math.min(imin * nums[i], nums[i]);
                max = max > imax ? max : imax;
            }
            return max;
        };

4. 最少硬幣找零

//給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。
// 示例 1:
// 輸入: coins = [1, 2, 5], amount = 11
// 輸出: 3 
// 解釋: 11 = 5 + 5 + 1
// 示例 2:
// 輸入: coins = [2], amount = 3
// 輸出: -1
//解題思路:所要金額可用amount減去coins中任一面值+1得到
//例如amount = 15,coins=[1,2,11,15],可由f(amount-coin)+1得到,即f(0)+1,f(4)+1,f(13)+1,f(14)+1
var coinsChange = function(amount,coins){
    let dp = Array.from({length: amount+1},item=>item=Infinity);
    dp[0] = 0;
    for(var i=1;i<=amount;i++){
        for(var coin of coins){
            console.log(dp)
            if(i-coin>=0){
                //i=1時,dp[1]=dp[0]+1=1
                dp[i] = Math.min(dp[i],dp[i-coin]+1)
            }
        }
    }
    return dp[amount]===Infinity?-1:dp[amount]
}

console.log(coinsChange(16,[1,2,5]))

5. 最長公共子序列

 //     給定兩個字符串 text1 和 text2,返回這兩個字符串的最長公共子序列。
        // 一個字符串的 子序列 是指這樣一個新的字符串:它是由原字符串在不改變字符的相對順序的情況下刪除某些字符(也可以不刪除任何字符)后組成的新字符串。
        // 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。兩個字符串的「公共子序列」是這兩個字符串所共同擁有的子序列。
        // 若這兩個字符串沒有公共子序列,則返回 0。
        // 示例 1:
        // 輸入:text1 = "abcde", text2 = "ace" 
        // 輸出:3  
        // 解釋:最長公共子序列是 "ace",它的長度為 3。
        // 示例 2:
        // 輸入:text1 = "abc", text2 = "abc"
        // 輸出:3
        // 解釋:最長公共子序列是 "abc",它的長度為 3。
        // 示例 3:
        // 輸入:text1 = "abc", text2 = "def"
        // 輸出:0
        // 解釋:兩個字符串沒有公共子序列,返回 0
        解題思路:列出一個二維dy數組,列出每個位置子序列長度
        var longestCommonSubsequence = function (text1, text2) {
            var m = text1.length,//rows
                n = text2.length, //cols
                dp = Array.from({ length: n + 1 }, item => item = new Array(m + 1).fill(-Infinity));
            dp[0][0] = 0;
            for (var i = 0; i <= n; i++) {
                for (var j = 0; j <= m; j++) {
                    if (i === 0 || j === 0) {//有一方為0結論為0
                        dp[i][j] = 0
                    } else if (text1[j-1] === text2[i-1]) {//i,j對應字符相等
                        dp[i][j] = dp[i - 1][j - 1] + 1
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }
                }
            }
            return dp[n][m];
        };
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容