下降的路径就是从第一行任一个元素出发,只能直着或斜着走到下一行,直到到达最后一行,返回形成的路径中最小的路径和。
思路:
DP
从下往上推,
在最后一行选一个元素,那么它是从哪里过来的?是从上一行的j-1, j, j+1 3个位置过来的。
设dp[ i ] [ j ]是从第一行任一元素到[ i][ j ]所在元素的所有路径的最小路径和。
那么dp[ i ][ j ] = min(dp[ i - 1][j - 1], dp[i - 1] [ j ], dp[i-1][j+1]) + matrix[ i ][ j ],
然后取dp[n-1]这一行的最小值即可。
public int minFallingPathSum(int[][] matrix) {
int n = matrix.length;
int res = 10000000;
int[][] dp = new int[n][n];
for(int j = 0; j < n; j++) dp[0][j] = matrix[0][j];
for(int i = 1; i < n; i++) {
for(int j = 0; j < n; j++) {
if(j == 0) {
dp[i][j] = Math.min(dp[i-1][j], dp[i-1][j+1]) + matrix[i][j];
} else if(j == n-1) {
dp[i][j] = Math.min(dp[i-1][j-1], dp[i-1][j]) + matrix[i][j];
} else {
dp[i][j] = Math.min(Math.min(dp[i-1][j-1], dp[i-1][j]), dp[i-1][j+1]) + matrix[i][j];
}
}
}
for(int j = 0; j < n; j++) {
res = Math.min(res, dp[n-1][j]);
}
return res;
}
上面的方法好理解,但不是最快的,最快的参考
class Solution {
int ans = Integer.MAX_VALUE;
public int minFallingPathSum(int[][] matrix) {
helper(matrix, matrix.length-2);
return ans;
}
void helper(int[][] matrix, int r) {
if(r<0) {
for(int i=0; i<matrix.length; i++) {
ans = Math.min(ans, matrix[0][i]);
}
return;
}
for(int i=0; i<matrix.length; i++) {
int minNextVal = matrix[r+1][i];
if(i>0) {
minNextVal = Math.min(minNextVal, matrix[r+1][i-1]);
}
if(i<matrix.length-1) {
minNextVal = Math.min(minNextVal, matrix[r+1][i+1]);
}
matrix[r][i] += minNextVal;
}
helper(matrix, r-1);
}
}