(动态规划) LeetCode64. 最小路径和

题目:
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7

方法一:动态规划(二维)
思路:
1、新建一个与原矩阵大小相同 dp 数组,dp(i, j)dp(i,j) 表示从坐标 (i, j)(i,j) 到右下角的最小路径权值。
2、初始化右下角的 dp 值为对应的原矩阵值
3、dp[i][j] = grid[i][j] + Math.min(dp[i + 1][j], dp[i][j + 1])
时间复杂度: O(m * n)
空间复杂度: O(m * n)

var minPathSum = function(grid) {
    let n = grid.length;
    if(!n) return 0
    let m = grid[0].length;
    let dp = Array.from(new Array(n), () => new Array(m).fill(0))
    for(let i = n - 1; i >= 0; i--){
        for(let j = m - 1; j >= 0; j--){
            if(i === n - 1 && j !== m - 1)
                dp[i][j] = grid[i][j] + dp[i][j + 1]
            else if(i !== n - 1 && j === m - 1)
                dp[i][j] = grid[i][j] + dp[i + 1][j]
            else if(i !== n - 1 && j !== m - 1)
                dp[i][j] = grid[i][j] + Math.min(dp[i + 1][j], dp[i][j + 1])
            else
                dp[i][j] = grid[i][j]
        }
    }
    return dp[0][0]
};  

方法二:动态规划(一维)
思路:
1、用一维数组来代替二维数组,dp 数组的大小和行大小相同
2、因为对于某个固定状态,只需要考虑下方和右侧的节点
3、首先初始化 dp 数组最后一个元素是右下角的元素值,然后向左移更新每个 dp(j):dp[i][j] = grid[i][j] + Math.min(dp[i + 1][j], dp[i][j + 1])
时间复杂度: O(m * n)
空间复杂度: O(m)


var minPathSum = function(grid) {
    let n = grid.length;
    if(!n) return 0
    let m = grid[0].length;
    let dp = Array.from(m);
    for(let i = n - 1; i >= 0; i--){
        for(let j = m - 1; j >= 0; j--){
            if(i === n - 1 && j !== m - 1)
                dp[j] = grid[i][j] + dp[j + 1]
            else if(i !== n - 1 && j === m - 1)
                dp[j] = grid[i][j] + dp[j]
            else if(i !== n - 1 && j !== m - 1)
                dp[j] = grid[i][j] + Math.min(dp[j], dp[j + 1])
            else
                dp[j] = grid[i][j]
        }
    }
    return dp[0]
};  


方法三:动态规划(二维) 不需要额外空间
思路:
同方法一,直接在当前二维数组修改,不需要创建新的二维数组
时间复杂度: O(m * n)
空间复杂度: O(1)

var minPathSum = function(grid) {
    let n = grid.length;
    if(!n) return 0
    let m = grid[0].length;
    for(let i = n - 1; i >= 0; i--){
        for(let j = m - 1; j >= 0; j--){
            if(i === n - 1 && j !== m - 1)
                grid[i][j] = grid[i][j] + grid[i][j + 1]
            else if(i !== n - 1 && j === m - 1)
                grid[i][j] = grid[i][j] + grid[i + 1][j]
            else if(i !== n - 1 && j !== m - 1)
                grid[i][j] = grid[i][j] + Math.min(grid[i + 1][j], grid[i][j + 1])
            else
                grid[i][j] = grid[i][j]
        }
    }
    return grid[0][0]
};  

你可能感兴趣的:((动态规划) LeetCode64. 最小路径和)