动态规划问题:矩阵的最小路径和

题目:

给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。
示例:
m n 4 4
1 3 5 9
8 1 3 4
5 0 6 1
8 8 4 0
输出:12

解法一:

更新整个矩阵
第一行和第一列只需要直接求和更新即可
其余部分可以看到 矩阵只能从左边或者上边经过,只需要比较左边和上边的数的大小,取小的即可。

public int MinPathSum1(int[][] m){
	if (m == null || m.length == 0 || m[0] == null || m[0].length = 0){
		return 0;
	}
	int row = m.length;
	int col = m[0].length;
	int [][] dp = new int [row][col];
	dp[0][0] = m[0][0];
	for (int i = 1;i < row ;i++){
		dp[i][0] = dp[i-1][0] + m[i][0];
	}
	for (int j = 1;j < col; j++){
		dp[0][j] = dp[0][j-1] + m[0][j];
	}
	for (int i = 1;i < row;i++){
		for(int j =1; j < col; j++){
			dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1]) + m[i][j];
		}
	}
	return dp[row-1][col-1];
	

解法二

解法一的空间还可以压缩。8 1 3 4
可以只采用一个数组进行滚动更新。
为节省空间可以选择维度较小的数组开始。
迭代过程前几步 1 3 5 9 -> 1 4 9 18 -> 9 3 9 18 ->9 5 9 18

public int minPathSum2(int [][] m){
	if (m == null || m.length == 0 || m[0] == null || m[0].length = 0){
		return 0;
	}	
	int more = Math.max(m.length,m[0].length);// 行和列相对小的数
	int less = Math.min(m.length, m[0].length);// 行和列相对大的数
	boolean colIsMore = more == m[0].length;// 标志列是不是相对大的那个
	int[] dp = new int[less];
	dp[0] = m[0][0];
	for (i = 1;i < less; i++){
		dp[i] = dp[i-1] + (colIsMore ? m[0][i] : m[i][0]);
	}
	for (i = 1;i < more;i++){
		dp[0] = dp[0] + (colIsMore ? m[i][0] : m[0][i]);
		for (j = 1;j < less;j++){
			dp[i] = Math.min(dp[i], dp[i-1]) + (colIsMore ? m[i][j] : m[j][i]);
		}
	}
	return arr[more - 1];

备注 : 如果题目中需要打印起点到所有点之间的最小路径则不能使用空间压缩的方法。空间压缩后过程中的值会被覆盖,不可回溯。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值