【动态规划】64. 最小路径和

题目

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

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

示例:

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

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/minimum-path-sum 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


动态规划

很经典的动态规划题,动态规划是一种优化方法,一般用于求最值,它适用于后一阶段最优取决于上一阶段最优的问题,这类问题一定具备最优子结构,通过子问题的最优值得到原问题的最值,动态规划的过程实际上也是一个填表的过程

对于该题,需要求从左上角到右下角的最小路径,且只能向下或向右走,则大问题是从左上角走到右下角,大问题的上一阶段是两个子问题:

  • q 1 q_1 q1:从左上角走到右下角的左边一个位置
  • q 2 q_2 q2:从左上角走到右下角的上面一个位置

只要这两个子问题已知,则原问题的解就是 m i n ( q 1 , q 2 ) + g r i d [ m ] [ n ] min(q_1, q_2)+grid[m][n] min(q1,q2)+grid[m][n],同样的,子问题 q 1 q_1 q1 q 2 q_2 q2又对应了各自的两个子问题,因此可以从最小的子问题开始,即从左上角走到左上角,不断得到大问题的解,这个过程就是填表的过程,整个表填完则得到大问题的解

class Solution {
	public int m, n;

	public int minPathSum(int[][] grid) {
		m = grid.length;
		n = grid[0].length;
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				if (i > 0 && j > 0) {
					grid[i][j] = Math.min(grid[i][j - 1], grid[i - 1][j]) + grid[i][j];
				} else {
					if (i == 0 && j == 0)
						continue;
					if (i == 0)
						// top row
						grid[i][j] += grid[i][j - 1];
					if (j == 0)
						// left col
						grid[i][j] += grid[i - 1][j];
				}
			}
		}
		return grid[m - 1][n - 1];
	}
}

递归(超时)

正如上面介绍,原问题的解就是 m i n ( q 1 , q 2 ) + g r i d [ m ] [ n ] min(q_1, q_2)+grid[m][n] min(q1,q2)+grid[m][n],因此也可以使用递归法,但是效率比较低,超时。。。

class Solution {
	public int nums[][], m, n, min;

	public int minPathSum(int[][] grid) {
		m = grid.length;
		n = grid[0].length;
		nums = new int[m][n];
		min = Integer.MAX_VALUE;
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				nums[i][j] = grid[i][j];
		return walk(0, 0);
	}

	public int walk(int i, int j) {
		if (i >= m || j >= n)
			return Integer.MAX_VALUE;
		if (i == m - 1 && j == n - 1)
			// arrive at right down
			return nums[i][j];
		// down or right
		return Math.min(walk(i, j + 1), walk(i + 1, j)) + nums[i][j]; 
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值