LeetCode: 64. 最小路径和

91 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

64. 最小路径和

来源:力扣(LeetCode)

链接: leetcode.cn/problems/mi… 给定一个包含非负整数的 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

解法

  • 动态规划:路径相关的题目,可以使用BFS或者DFS进行解决,就是有些复杂。这里路径依赖于之前的状态,这里以动态规划的方法来解决。 动态规划:四个步骤:
    • 问题定义
    • 状态转移方程
    • 初始条件和边界情况
    • 确定计算顺序(自顶向下,还是自下向上)

问题定义: dp[i][j]表示走到位置(i, j)时候所获得的路径上的数字总和最小值

状态转移方程: 由于只能往右和向下走,那么到达(i,j)位置只可能是从左边或者上边得到

  • dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + grid[i][j] 这里如果不考虑权重的话,就不用加grid[i][j]

初始化条件和边界条件

  • dp[0][0] = grid[0][0]

确定计算顺序: 这个是从下向上的方向计算即可

代码实现

动态规划

python实现

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        dp = grid[:]

        # init first col only could be down
        for i in range(1, m):
            dp[i][0] = dp[i-1][0] + grid[i][0]
        
        # init first row, only could be right
        for j in range(1, n):
            dp[0][j] = dp[0][j-1] + grid[0][j]
        
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
        return dp[-1][-1]

c++实现

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();

        vector<vector<int>> dp = grid;
        for (int i=1; i<m; i++) {
            dp[i][0] = dp[i-1][0] + grid[i][0];
        }

        for (int j=1; j<n; j++) {
            dp[0][j] = dp[0][j-1] + grid[0][j];
        }

        for (int i=1; i<m; i++) {
            for (int j=1; j<n; j++) {
                dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
            }
        }
        return dp[m-1][n-1];

    }
};

复杂度分析

  • 时间复杂度: O(mn)O(m*n ) m行n列
  • 空间复杂度: O(mn)O(m*n)