前言
“这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战”
下降路径最小和
给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 **的 ****最小和 。
下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) 。
示例 1:
输入: matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出: 13
解释: 下面是两条和最小的下降路径,用加粗+斜体标注:
[[2,1,3], [[2,1,3],
[6,5,4], [6,5,4],
[7,8,9]] [7,8,9]]
思路分析
因为下一行选择的元素和当前行所选元素最多相隔一列
位置(i,j)的下降路径只与上一行相邻的元素 (i-1,j-1) (i-1,j) (i-1,j+1)有关
定义dp 数组 dp[i][j] 表示到当前元素的最小下将路径
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i-1][j + 1]) + matrix[i][j]
AC 代码:
public int minFallingPathSum(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[][] dp = new int[2][n];
for(int j=0;j<n;j++) dp[0 & 1][j] = matrix[0][j];
for(int i=1;i<m;i++){
for(int j=0;j<n;j++){
int left = j-1>=0? dp[(i-1) & 1][j-1] : Integer.MAX_VALUE;
int right = j+1 < n? dp[(i-1) & 1][j+1]:Integer.MAX_VALUE;
dp[i & 1][j] = Math.min(dp[(i-1) & 1][j], Math.min(left, right)) + matrix[i][j];
}
}
int ans = Integer.MAX_VALUE;
for(int j=0;j<n;j++) ans = Math.min(ans, dp[(m-1) & 1][j]);
return ans;
}
1289. 下降路径最小和 II
给你一个整数方阵 arr ,定义「非零偏移下降路径」为:从 arr 数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。
请你返回非零偏移下降路径数字和的最小值。
示例 1:
输入: arr = [[1,2,3],[4,5,6],[7,8,9]]
输出: 13
解释:
所有非零偏移下降路径包括:
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
下降路径中数字和最小的是 [1,5,7] ,所以答案是 13 。
提示:
1 <= arr.length == arr[i].length <= 200-99 <= arr[i][j] <= 99
思路分析:
解法与上一道题类似, 因为下一行选择的元素和当前行所选元素不可以在同一列
那么 位置(i,j) 依赖于上一行除了 位置(i-1,j)的其他元素
dp[i][j] = min(dp[i-1][x] ....) (x != j)
3 重for 循环
实际上 只关心上一行的最小值 和 次小值 即可
AC 代码:
使用有限的变量替换 3 重 for 循环
public int minFallingPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
int minIndex1 = -1;
int minIndex2 =-1;
for(int j=0;j<n;j++){
dp[0][j] = grid[0][j];
if(grid[0][j] < (minIndex1 == -1 ? Integer.MAX_VALUE:grid[0][minIndex1])){
minIndex2 = minIndex1;
minIndex1 = j;
}else if(grid[0][j] < (minIndex2 == -1 ? Integer.MAX_VALUE:grid[0][minIndex2])){
minIndex2 = j;
}
}
for(int i=1;i<m;i++){
int curMinIndex1 = -1;
int curMinIndex2 = -1;
for(int j=0;j<n;j++){
if(j == minIndex1){
dp[i][j] = grid[i][j] + dp[i-1][minIndex2];
}else{
dp[i][j] = grid[i][j] + dp[i-1][minIndex1];
}
if(dp[i][j] < (curMinIndex1 == -1 ? Integer.MAX_VALUE:dp[i][curMinIndex1])){
curMinIndex2 = curMinIndex1;
curMinIndex1 = j;
}else if(dp[i][j] < (curMinIndex2 == -1 ? Integer.MAX_VALUE:dp[i][curMinIndex2])){
curMinIndex2 = j;
}
}
minIndex1 = curMinIndex1;
minIndex2 = curMinIndex2;
}
int ans = Integer.MAX_VALUE;
for(int j=0;j<n;j++) ans = Math.min(ans, dp[m - 1][j]);
return ans;
}