【LeetCode】每日一题 最小路径和

84 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

64. 最小路径和

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

说明: 每次只能向下或者向右移动一步。

「示例1:」
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 13111 的总和最小。
「示例2:」
输入:grid = [[1,2,3],[4,5,6]]
输出:12
「提示:」
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 100

解题思路

// 第一种
动态规划解法
创建一个dp数组,里面每个值代表着到这一点的最短路径和,例如dp[2][2],就代表到达grid[2][2]的最短路径和,推出dp方程为:
dp[i][j] = Math.min(dp[i - 1][j] + grid[i][j], dp[i][j - 1] + grid[i][j])
​
// 第二种
到达sum(m-1,n-1)最小,则上一步是最小 min( minSum(m-2,n-1), minSum(m-1,n-2)), 得到 minSum(m-1,n-1) = min( minSum(m-2,n-1), minSum(m-1,n-2)) + 1
​
要是当前最小 则满足两个条件,
​
可以到达 则(m-2,n-1) OR (m-1,n-2)
上一步最小 minSum(m-1,n-1) = min( minSum(m-2,n-1)

代码实现

// 第一种
var minPathSum = function(grid) {
  // 行
  const row = grid.length;
  // 列
  const col = grid[0].length;
​
  // 创建dp数组
  const dp = Array.from(new Array(row), () => new Array(col).fill(1));
  
  // 到达第一个点的路径和肯定为grid[0][0]值本身
  dp[0][0] = grid[0][0];
  
  // 求第一行每个点的最短路径和
  for (let i = 1; i < col; i++) {
    dp[0][i] = grid[0][i] + dp[0][i - 1];
  }
​
  // 求第一列每一行的最短路径和
  for (let j = 1; j < row; j++) {
    dp[j][0] = grid[j][0] + dp[j - 1][0];
  }
​
  // 从 grid[1][1]开始计算每一点的最短路径和,例如计算grid[1][1]该点的最短路径和,仅需比较 dp[0][1] + grid[1][1] 与 dp[1][0] + grid[1][1]
  // 比较两者大小,谁最小则取谁的值
  for (let i = 1; i < row; i++) {
    for (let j = 1; j < col; j++) {
      dp[i][j] = Math.min(dp[i - 1][j] + grid[i][j], dp[i][j - 1] + grid[i][j]);
    }
  }
​
  return dp[row - 1][col - 1];
};
​
// 第二种
var minPathSum = function(grid) {
    if(grid.length == 0){
        return 0;
    }
    let minSum = [];
    let m = grid.length;
    let n = grid[0].length;
    for(let i = 0; i<grid.length; i++){
        minSum[i] = [];
    }
    minSum[0][0] = grid[0][0];
    for(let i = 0; i < m; i++){
        for(let j = 0;j < n; j++){
            if(i==0 && j==0){
                minSum[i][j] =  grid[i][j]
                continue;
            } 
            if(i == 0 && j!=0){
                minSum[i][j] = minSum[i][j-1] + grid[i][j]
                continue;
            }
            if(j == 0 && i!=0){
                minSum[i][j] = minSum[i-1][j] + grid[i][j]
                continue;
            }
            minSum[i][j] = Math.min(minSum[i-1][j], minSum[i][j-1]) + grid[i][j];
        }
    }
    return minSum[m-1][n-1];
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;