1、题目链接
2、解题思路
这道题的意思是说给你一个方形(n*n)的整数数组,让你从第一排的任意一个位置开始走,一行一行的走,就比如第一次你从初始状态走到了第一行,第二次从第一行走到了第二行,以此类推......有个条件,每次往下走一行的时候,你必须保证你下一行所在的列必须在上一行所在列的左边/右边/本身列,一开始我是想直接暴力递归来计算的,但是到后面发现肯定会超时,因为最多可能有100行100列,除了首末两列,其余列均有三种可能的走法,这样的话就会导致时间超时,但是仔细想想,这道题和走台阶的题有点像,从第0阶走到第n阶,每次有两种走法那道题,单纯的递归为什么会超时,就是因为我们重复计算太多,如果我们可以用dp来保存计算过的值,然后用的时候直接取就好了,这样就能减少重复计算的次数,从而避免超时,下面来看代码,注释写的还是很详细的:
3、代码
public int minFallingPathSum(int[][] A) {
int len = A.length;
int[][] dp = new int[len + 1][len + 1];
// 第一行,因为我们是从第一行开始往下走的,所以从初始状态到第一行的最短路径就等于该数字本身
for (int i = 0; i < len; i++) {
dp[0][i] = A[0][i];
}
for (int i = 1; i < len; i++) { // 从第二行开始遍历
for (int j = 0; j < len; j++) {
if (j == 0) { // 第一列,只有两种情况,右边和本身
// 该位置的最小路径肯定是等于该点的值加上上一行同列以及上一行同列右边的最小路径
dp[i][j] = A[i][j] + Math.min(dp[i - 1][j], dp[i - 1][j + 1]);
} else if (j == len - 1) { //最后一列,也是只有两种情况,左边和本身
// 该位置的最小路径肯定是等于该点的值加上上一行同列以及上一行同列左边的最小路径
dp[i][j] = A[i][j] + Math.min(dp[i - 1][j - 1], dp[i - 1][j]);
} else { //中间列,有三种情况,本身,左和右
// 该位置的最小路径肯定是等于该点的值加上上一行同列以及上一行同列左右两边的最小路径
dp[i][j] = A[i][j] + Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i - 1][j + 1]));
}
}
}
// 我们要求到达最后一行的最短路径,那么,先假设最短路径是最后一行的第一列
int result = dp[len - 1][0];
// 然后遍历最后一行的每一列,取出最短路径
for (int i = 0; i < len; i++) {
result = Math.min(result, dp[len - 1][i]);
}
return result;
}
4、结果
