暴力递归(时间复杂度过高)
每个位置都尝试向右走和向左走,时间复杂度较高,为 O(2 ^ (n * m))
public class Solution{
private int minPathSum;
/**
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
public int minPathSum (int[][] matrix) {
// write code here
int n = matrix.length;
if (n == 0) return 0;
int m = matrix[0].length;
minPathSum = Integer.MAX_VALUE;
findMinPathSum(0, 0, n - 1, m - 1, matrix, 0);
return minPathSum;
}
/**
* 暴力递归,每个位置都尝试向右和向下两种走法,
* 时间复杂度较高,为 O(2 ^ (n * m))
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
private void findMinPathSum(int i, int j, int maxI, int maxJ, int[][] matrix, int pathSum) {
if (i > maxI || j > maxJ)
return;
pathSum += matrix[i][j];
if (i == maxI && j == maxJ) {
minPathSum = Math.min(pathSum, minPathSum);
return;
}
findMinPathSum(i + 1, j, maxI, maxJ, matrix, pathSum);
findMinPathSum(i, j + 1, maxI, maxJ, matrix, pathSum);
}
}
动态规划
时间复杂度 O(n * m),空间复杂度O(n * m)
/**
* 动态规划,时间复杂度 O(n * m),空间复杂度O(n * m)
* 状态dp[i][j],从起点到达matrix[i][j]的最小路径
*
* 状态初始化:
* dp[0][0] = matrix[0][0];
* for (int i = 0; i < n - 1; i++){
* dp[i + 1][0] = matrix[i + 1][0] + dp[i][0];
* }
* for (int j = 0; j < m - 1; j++){
* dp[0][j + 1] = matrix[0][j + 1] + dp[0][j];
* }
*
* 状态转移方程:
* dp[i][j] = matrix[i][j] + Math.min(dp[i][j - 1], dp[i - 1][j]) (前提是数组不越界)
*
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
public int minPathSum (int[][] matrix) {
// write code here
int n = matrix.length;
if (n == 0) return 0;
int m = matrix[0].length;
int[][] dp = new int[n][m];
dp[0][0] = matrix[0][0];
for (int i = 0; i < n - 1; i++){
dp[i + 1][0] = matrix[i + 1][0] + dp[i][0];
}
for (int j = 0; j < m - 1; j++){
dp[0][j + 1] = matrix[0][j + 1] + dp[0][j];
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++)
dp[i][j] = matrix[i][j] + Math.min(dp[i - 1][j], dp[i][j - 1]);
}
return dp[n - 1][m - 1];
}
压缩空间的动态规划(可以降低空间复杂度)
该压缩空间的方法几乎可以用到所有二维动态规划表。
/**
* 压缩空间的动态规划,时间复杂度 O(n * m),空间复杂度O(n)
* 由于我们的动态规划,从起点开始,按从左到右,从上到下的顺序遍历,所以
* 可以将二维的状态变量压缩成一维的状态变量 (既不需要考虑行号)
*
* 状态dp[i]:
* 更新之前,
* dp[i - 1]表示到当前位置matrix[][i + 1]的左一位置的最小路径
* dp[i]表示到当前位置matrix[][i + 1]的上一位置的最小路径
* 更新之后,
* dp[i]表示到当前位置matrix[][i + 1]的最小路径
*
* 状态初始化:
* int[] dp = new int[m + 1];
* for (int i = 0; i < m + 1; i++)
* dp[i] = Integer.MAX_VALUE;
* dp[1] = 0;
*
* 状态转移方程:
* dp[i] = Math.min(dp[i - 1], dp[i]) + matrix[i - 1][j - 1]; (前提是数组不越界)
*
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
public int minPathSum3 (int[][] matrix) {
// write code here
int n = matrix.length;
if (n == 0) return 0;
int m = matrix[0].length;
int[] dp = new int[m + 1];
// 状态初始化
for (int i = 0; i < m + 1; i++)
dp[i] = Integer.MAX_VALUE;
dp[1] = 0;
// 动态规划
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)
dp[j] = Math.min(dp[j - 1], dp[j]) + matrix[i - 1][j - 1];
}
return dp[m];
}