题目

leetcode 64. 最小路径和

提示:

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

题解

方法一:递归解法(超时)

right 表示当前向已右走的步数,down 表示当前已向下走的步数,cur 表示当前走过的路径和。

此方法超时,应该使用 (方法二)动态规划解法。

public static int minPathSum1(int[][] grid) {int right = 0, down = 0;return getMinSum(0, right, down, grid);
}public static int getMinSum(int cur, int right, int down, int[][] grid) {int m = grid.length - 1; // 行边界int n = grid[0].length - 1; // 列边界cur += grid[down][right];if (right == n && down == m) { // 到终点return cur;} else if (right == n) { // 右边界return getMinSum(cur, right, down + 1, grid);} else if (down == m) { // 下边界return getMinSum(cur, right + 1, down, grid);} else {return Math.min(getMinSum(cur, right, down + 1, grid), getMinSum(cur, right + 1, down, grid));}
}

方法二:动态规划

由于路径的方向只能是向下或向右,因此网格的第一行的每个元素只能从左上角元素开始向右移动到达,网格的第一列的每个元素只能从左上角元素开始向下移动到达,此时的路径是唯一的,因此每个元素对应的最小路径和即为对应的路径上的数字总和。

对于不在第一行和第一列的元素,可以从其上方相邻元素向下移动一步到达,或者从其左方相邻元素向右移动一步到达,元素对应的最小路径和等于其上方相邻元素与其左方相邻元素两者对应的最小路径和中的最小值加上当前元素的值。由于每个元素对应的最小路径和与其相邻元素对应的最小路径和有关,因此可以使用动态规划求解。

创建二维数组 dp,与原始网格的大小相同,dp[i][j] 表示从左上角出发到 (i,j) 位置的最小路径和。显然,dp[0][0]=grid[0][0]。对于 dp 中的其余元素,通过以下状态转移方程计算元素值。

状态转移方程:

  • 当 i>0 且 j=0 时,dp[i][0] = dp[i-1][0] + grid[i][0]

  • 当 i=0 且 j>0 时,dp[0][j] = dp[0][j-1] + grid[0][j]

  • 当 i>0 且 j>0 时,dp[i][j] = min(dp[i−1][j],dp[i][j−1]) + grid[i][j]

最后得到 dp[m-1][n-1] 的值,即为从网格左上角到网格右下角的最小路径和。

代码

public static int minPathSum2(int[][] grid) {if (grid == null || grid.length == 0 || grid[0].length == 0) {return 0;}int rows = grid.length, columns = grid[0].length;int[][] dp = new int[rows][columns];dp[0][0] = grid[0][0];for (int i = 1; i < rows; i++) { // 计算最左列的值:此时左边是边界dp[i][0] = dp[i - 1][0] + grid[i][0];}for (int j = 1; j < columns; j++) { // 计算最上行的值:此时上边是边界dp[0][j] = dp[0][j - 1] + grid[0][j];}for (int i = 1; i < rows; i++) { // 其余元素for (int j = 1; j < columns; j++) {dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];}}return dp[rows - 1][columns - 1];
}

复杂度分析

  • 时间复杂度:O(m*n),其中 m 和 n 分别是网格的行数和列数。需要对整个网格遍历一次,计算 dp 的每个元素的值。

  • 空间复杂度:O(m*n),其中 m 和 n 分别是网格的行数和列数。创建一个二维数组 dpdp,和网格大小相同。
    注:空间复杂度可以优化,例如每次只存储上一行的 dp 值,则可以将空间复杂度优化到 O(n)。

附:4*4矩阵的16步完整过程示例















附:完整代码(含测试用例)

class Solution {public static void main(String[] args) {//        int[][] grid = {{1, 2, 3}, {4, 5, 6}};int[][] grid = {{3, 8, 6, 0, 5, 9, 9, 6, 3, 4, 0, 5, 7, 3, 9, 3}, {0, 9, 2, 5, 5, 4, 9, 1, 4, 6, 9, 5, 6, 7, 3, 2}, {8, 2, 2, 3, 3, 3, 1, 6, 9, 1, 1, 6, 6, 2, 1, 9}, {1, 3, 6, 9, 9, 5, 0, 3, 4, 9, 1, 0, 9, 6, 2, 7}, {8, 6, 2, 2, 1, 3, 0, 0, 7, 2, 7, 5, 4, 8, 4, 8}, {4, 1, 9, 5, 8, 9, 9, 2, 0, 2, 5, 1, 8, 7, 0, 9}, {6, 2, 1, 7, 8, 1, 8, 5, 5, 7, 0, 2, 5, 7, 2, 1}, {8, 1, 7, 6, 2, 8, 1, 2, 2, 6, 4, 0, 5, 4, 1, 3}, {9, 2, 1, 7, 6, 1, 4, 3, 8, 6, 5, 5, 3, 9, 7, 3}, {0, 6, 0, 2, 4, 3, 7, 6, 1, 3, 8, 6, 9, 0, 0, 8}, {4, 3, 7, 2, 4, 3, 6, 4, 0, 3, 9, 5, 3, 6, 9, 3}, {2, 1, 8, 8, 4, 5, 6, 5, 8, 7, 3, 7, 7, 5, 8, 3}, {0, 7, 6, 6, 1, 2, 0, 3, 5, 0, 8, 0, 8, 7, 4, 3}, {0, 4, 3, 4, 9, 0, 1, 9, 7, 7, 8, 6, 4, 6, 9, 5}, {6, 5, 1, 9, 9, 2, 2, 7, 4, 2, 7, 2, 2, 3, 7, 2}, {7, 1, 9, 6, 1, 2, 7, 0, 9, 6, 6, 4, 4, 5, 1, 0}, {3, 4, 9, 2, 8, 3, 1, 2, 6, 9, 7, 0, 2, 4, 2, 0}, {5, 1, 8, 8, 4, 6, 8, 5, 2, 4, 1, 6, 2, 2, 9, 7}};System.out.println(minPathSum1(grid));System.out.println(minPathSum2(grid));}/*** 递归解法(超时)*/public static int minPathSum1(int[][] grid) {int right = 0, down = 0;return getMinSum(0, right, down, grid);}public static int getMinSum(int cur, int right, int down, int[][] grid) {int m = grid.length - 1; // 行边界int n = grid[0].length - 1; // 列边界cur += grid[down][right];if (right == n && down == m) { // 到终点return cur;} else if (right == n) { // 右边界return getMinSum(cur, right, down + 1, grid);} else if (down == m) { // 下边界return getMinSum(cur, right + 1, down, grid);} else {return Math.min(getMinSum(cur, right, down + 1, grid), getMinSum(cur, right + 1, down, grid));}}/*** 动态规划解法(推荐)*/public static int minPathSum2(int[][] grid) {if (grid == null || grid.length == 0 || grid[0].length == 0) {return 0;}int rows = grid.length, columns = grid[0].length;int[][] dp = new int[rows][columns];dp[0][0] = grid[0][0];for (int i = 1; i < rows; i++) { // 计算最左列的值:此时左边是边界dp[i][0] = dp[i - 1][0] + grid[i][0];}for (int j = 1; j < columns; j++) { // 计算最上行的值:此时上边是边界dp[0][j] = dp[0][j - 1] + grid[0][j];}for (int i = 1; i < rows; i++) { // 其余元素for (int j = 1; j < columns; j++) {dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];}}return dp[rows - 1][columns - 1];}
}

leetcode 64. 最小路径和(递归 / 动态规划解法图解)(Java版)相关推荐

  1. leetcode - 64. 最小路径和

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

  2. LeetCode 64最小路径和65有效数字66加一

    原创公众号:bigsai 专注于Java.数据结构与算法,一起进大厂不迷路! 关注后回复进群即可加入力扣打卡群,欢迎划水.近期打卡: LeetCode打卡 52八皇后Ⅱ&53最大子序和& ...

  3. 93. Leetcode 64. 最小路径和 (动态规划-路径规划)

    步骤一.确定状态: 1.确定原问题中变化的变量个数 2.考虑最后一步 右下角坐标设为(m-1,n-1) 那么前一步一定是在(m-2,n-1)或者(m-1,n-2) 步骤二.推断状态方程: f[i][j ...

  4. LeetCode 64.最小路径和(动态规划)

    题目描述 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], [1,5 ...

  5. 2022-4-19 Leetcode 64.最小路径和 ——【简单的动态规划】

    自己写的二维dp class Solution {public:int minPathSum(vector<vector<int>>& grid) {if(grid.e ...

  6. LeetCode 64. 最小路径和(DP)

    文章目录 1. 题目信息 2. 解题 1. 题目信息 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示 ...

  7. leetcode 64. 最小路径和

    难度:中等 频次:54 题目:给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 解题思路:动态 ...

  8. LeetCode 64 最小路径和

    题目描述 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和 为最小.说明:每次只能向下或者向右移动一步. 题解 动态规划 代码 class ...

  9. Leetcode 64. 最小路径和 -- DP算法

    Time: 20190831 题目描述 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: ...

最新文章

  1. ASP.NET 163 smtp服务器响应为:User has no permission
  2. 计算机科学期刊拒稿概率大吗,发表论文初审过了复审被拒概率高不高
  3. springboot系列八、springboot整合kafka
  4. 运维监控工具之 Nagios 客户端安装(二)
  5. 网页中弹出模式对话框
  6. 文本的数据导入到数据库中 mysql
  7. Python基础学习总结、学习展望
  8. Dubbo学习总结(8)——阿里开源框架:Dubbo2.7 三大新特性详解!
  9. 基于MicroPython的家庭可燃气体泄露微信报警器
  10. Atitit 登录票据安全法 目录 1.1. cookie对象规范 1 1.2. Cookie加解密 1 1.3. Cookie密文动态更换,根据一个时间3天比如 1 1.4. 服务端撤销key 1
  11. Linux系统镜像源替换
  12. 软件安装 | SolidWorks2016软件安装,SW2010-2016.Activator.GUI.SSQ激活闪退解决办法
  13. matplotlib-27 内嵌环形饼图
  14. java加密算法之MD5篇
  15. 如何使用Etcd来完成选举
  16. 2018 rust卡石头教程_rust地上的石头怎么捡 | 手游网游页游攻略大全
  17. 考研英语——长难句语法
  18. 微信小程序直播有哪些推广技巧?
  19. python学习-绪
  20. 转:目前游戏行业内部主要几款游戏…

热门文章

  1. POJ - 1966 Cable TV Network(最小割-最大流)
  2. js:点击button后返回值
  3. php中add函数,php中addslashes()和addclashes()函数的区别分析
  4. matlab求被21整除,用matlab求[100,999]之间能被21整除的数的个数,还有建立一个字符串向量,删除大写字母._...
  5. python支持的编程范式有_【Python学习手册】chapter1 前面
  6. 从蓝桥杯来谈Fibonacci数列
  7. Codeforces Beta Round #1--C题(多边形求最小面积)
  8. PTA第3章-2 查验身份证 (15 分)
  9. SQLServer附加数据库提示“版本为661,无法打开,支持655版本……”
  10. COM编程之二 接口