力扣(LeetCode)刷题第64题:最小路径和


前言

题目地址:最小路径和

一、分析题目

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

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

在这里插入图片描述

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j]<= 100

拿到这个题,你该如何分析呢?怎么就知道是属于动态规划的题目呢?

我觉得你如果做的多了,可能一看就看出来了,或者你试着其他的思路是否可以解决这种问题,对于一个题目是否是动态规划的问题,你可以从以下几个方面来看。

动态规划满足三个性质:最优子结构、无后效性和大量重复子问题。
关于这个三个性质的解释,可以参考知乎的这篇文章:怎样学好动态规划?

二、解题思路

1.找出DP状态

此题需要求出从左上角出发,到达坐标(m,n)的路径数字和最小值。因此不难想到,子问题就是从左上角出发,到达坐标(i,j)的路径数字和最小值。

f[i][j]表示从左上角到坐标(i,j)的路径数字和最小值,原问题即可被划分为多个求最优值的子问题,且由于每次只能向下或向右移动一步,因此 f[i][j]的取值由f[i-1][j]f[i][j-1]的值决定,即符合「最优子结构原则」。

进一步验证,可以发现, f[i][j] 的取值与f[i-1][j]f[i][j-1]所对应的具体路径无关,因此符合「无后效性」。

2.找出DP状态转移方程

确定完「DP 状态」后,继续确定「DP 转移方程」。

在这里插入图片描述

这里需要注意边界问题,比如第一行和第一列,只能向下或者向右运动。

3.代码部分

1.Java版本

class Solution {
    public int minPathSum(int[][] grid) {
        //先判断数据是否为空
        if(grid==null||grid.length==0||grid[0].length==0){
            return 0;
        }
        int rows = grid.length;//行
        int column = grid[0].length;//列
        int [][]dp = new int[rows][column];//dp数组
        dp[0][0] = grid[0][0];//左上角元素值
        for(int i=0;i<rows;i++){
            for(int j=0;j<column;j++){
                if(i==0&&j==0){
                    continue;
                }
                else if(i==0&&j!=0){//第一行的元素
                    dp[0][j] = dp[0][j-1]+grid[0][j];

                }
                else if(i!=0&&j==0){//第一列的元素
                    dp[i][0] = dp[i-1][0]+grid[i][0];
                }
                else{
                    dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
                }
            }
        }
        return dp[rows-1][column-1];
    }
}

在这里插入图片描述
2.C++版本

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        //判断是否为空
        if (grid.size() == 0 || grid[0].size() == 0) {
            return 0;
        }
        int rows = grid.size(), columns = grid[0].size();
        auto dp = vector < vector <int> > (rows, vector <int> (columns));
        dp[0][0] = grid[0][0];//初值为左上角
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if(i==0&&j==0){
                    continue;
                }
                else if(i==0&&j!=0){
                    dp[0][j] = dp[0][j-1]+grid[0][j];
                }
                else if(i!=0&&j==0){
                    dp[i][0] = dp[i-1][0]+grid[i][0];
                }
                else{
                     dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];//状态转移方程
                } 
            }
        }
        return dp[rows - 1][columns - 1];
    }
};

在这里插入图片描述
3.Python3版本

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        #判断list是否为空
        if not grid or not grid[0]:
            return 0
        
        rows, columns = len(grid), len(grid[0])
        dp = [[0] * columns for _ in range(rows)]
        dp[0][0] = grid[0][0]
        for i in range(0, rows):
            for j in range(0, columns):
                if i==0 and j==0:
                    continue
                elif i==0 and j!=0:
                     dp[0][j] = dp[0][j - 1] + grid[0][j]
                elif i!=0 and j==0:
                     dp[i][0] = dp[i - 1][0] + grid[i][0]
                else:
                    dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]
        return dp[rows - 1][columns - 1]

在这里插入图片描述

三、总结

提示:这个题在动态规划里面算一个中等难度的题目,感觉这块内容确实比较让头头大,只能多做题,多总结了。
在这里插入图片描述

Java、C++和Python的运行时间和内存消耗的对比?Java居然用这么多?

在这里插入图片描述

记录时间:2020年11月19日

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值