LeetCode偶爾一題 —— 64. 最小路徑和

題目描述

給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和爲最小。
說明:每次只能向下或者向右移動一步。
示例:

輸入:
[
[1,3,1],  
[1,5,1],  
[4,2,1]  

]
輸出: 7
解釋: 因爲路徑 1→3→1→1→1 的總和最小。

分析題目

遞歸

對於有些題目,如果我們一下子想不出來解題思路,其實可以稍微對它分析一下,那麼自然就會找到解題的辦法。
根據題中描述,我們知道每次只能向下或者向右移動一步,我們以此爲依據畫出示例中所有可能的路徑👇

很明顯這是一個樹形結構,我們只要算出每個頭結點葉子結點所經過的路徑和,它們中最小的值就是題目中要求的最小路徑和,因此我們可以嘗試用深度優先搜索來解決它,第一版程序👇

var minPathSum = function (grid) {
    return dfs(0, 0)
    function dfs (i, j) {
        if (i === grid.length || j === grid[0].length) {
            return Number.MAX_SAFE_INTEGER
        }
        if (i === grid.length - 1 && j === grid[0].length - 1) {
            return grid[i][j]
        }
        return grid[i][j] + Math.min(dfs(i + 1, j), dfs(i, j + 1))
    }
}

動態規劃

細心的你可能已經發現,這道題其實可以把它分解爲一個個子問題,而我們只要解決了子問題,那麼只要把子問題合併起來就能給出解。
怎麼說呢?原題目讓我們求到 grid[i][j] 的最小路徑,那麼我們只要找到 grid[i][j]上一個或者左一個中和它加起來最小的一個。換成代碼也就是求👉 min = Math.min(grid[i][j] + grid[i - 1][j], gird[i][j] + grid[i][j-1])

具體實現如下👇

var minPathSum = function(grid) {
    let x = grid.length - 1, y = grid[0].length - 1
    for (let i = 0; i <= x; i++) {
        for (let j = 0; j <= y; j++) {
            let tmp = grid[i][j]
            if (j === 0) {
                if (i > 0) {
                    grid[i][j] = grid[i - 1][j] + tmp
                }
            } else {
                if (i > 0) {
                    grid[i][j] = Math.min(grid[i - 1][j] + tmp, grid[i][j - 1] + tmp)
                } else {
                    grid[i][j] = grid[i][j - 1] + tmp
                }
            }
        }
    }
    return grid[x][y]
};

原題地址: https://leetcode-cn.com/probl...
代碼不定時更新,歡迎 star 我的 repo

掃描下方的二維碼或搜索「tony老師的前端補習班」關注我的微信公衆號,那麼就可以第一時間收到我的最新文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章