题目
思路与算法
- 这题和之前做过的不同路径Ⅰ,不同路径Ⅱ基本一致,状态方程式也基本一致,没有什么太多的思路,第一种方法就直接暴力枚举所有的节点到末尾的距离就行了。状态方程:dp[i][j] =grid[i][j] + min{dp[i+1][j],dp[i][j+1]}
- 第二种方法是直接计算一下每次的权值,存入对应的相同大小的数组中即可,可以从左上角开始,也可以从右下角开始算,结果不变。实际上可以不用新建数组,空间复杂度可以优化降低,但时间复杂度不变,因此不予列举,
代码实现
方法一
package com.immunize.leetcode.minPathSum;
/**
* 方法一: 根据动态状态方程直接写:dp[i][j] =grid[i][j] + min{dp[i+1][j],dp[i][j+1]}
*
* TLE
*
* @author Mr IMMUNIZE
*
*/
public class Solution {
// 根据动态方程,当前节点的到达路径等于其右边的点和其下边的点的路径之和
// 写出从(i,j)到达右下角的路径值的计算
private int calculate(int i, int j, int[][] grid) {
// 特殊情况处理:边界点和终点的计算
// 超出边界的处理
if (i == grid.length || j == grid[0].length) {
return Integer.MAX_VALUE;
}
// 终点的计算
if (i == grid.length - 1 && j == grid[0].length - 1) {
return grid[i][j];
}
// 状态方程
return Math.min(calculate(i + 1, j, grid), calculate(i, j + 1, grid)) + grid[i][j];
}
public int minPathSum(int[][] grid) {
return calculate(0, 0, grid);
}
}
方法二
package com.immunize.leetcode.minPathSum;
/**
* 对方法一进行了优化,不枚举,直接计算出权重填入数组即可。
*
* @author Mr IMMUNIZE
*
*/
public class Solution2 {
public int minPathSum(int[][] grid) {
// 初始化变量,新建权重二维数组
int len1 = grid.length;
int len2 = grid[0].length;
int[][] weight = new int[len1][len2];
// 对数组进行整体的遍历,倒序遍历,每次将权重值存入对应的位置
for (int i = len1 - 1; i >= 0; i--) {
for (int j = len2 - 1; j >= 0; j--) {
// 如果是右下角的位置,则权重为其值
if (i == len1 - 1 && j == len2 - 1) {
weight[i][j] = grid[i][j];
}
// 最后一行的位置,权重为weight[i][j+1] + grid[i][j]
if (i == len1 - 1 && j != len2 - 1) {
weight[i][j] = weight[i][j + 1] + grid[i][j];
}
// 最后一列的位置,权重为weight[i+1][j] + grid[i][j]
if (i != len1 - 1 && j == len2 - 1) {
weight[i][j] = weight[i + 1][j] + grid[i][j];
}
// 其余位置的值,权重为Math.min(weight[i+1][j],weight[i][j+1])+grid[i][j]
if (i != len1 - 1 && j != len2 - 1) {
weight[i][j] = Math.min(weight[i + 1][j], weight[i][j + 1]) + grid[i][j];
}
}
}
// 遍历结束后直接返回weight[0][0]即可
return weight[0][0];
}
}
时间复杂度分析
方法一:(枚举法)每次有2条路可以选择,除了最后一行一列,但不影响复杂度O(2^(m+n))
方法二:需要遍历一遍数组,O(m*n)