目录
1289. 下降路径最小和 II - 力扣(LeetCode)
1289. 下降路径最小和 II - 力扣(LeetCode)
思路解析
首先关注到这道题是一个 “路径最优化” 的题目。因此,我们通常可以使用 DAGDP(有向图动态规划) 解决。
所以,我们的解决算法关注到 “动态规划”。接下来我们分析最优结构的特征信息。因为我们需要返回最小路径和,那么我们的最优子结构应该存放 最小路径和。接下来,因为我们的起点是不固定的,而终点是固定可知的。所以我们不妨记 dp(i, j) 表示以第 i 行第 j 列为终点的最小和。
状态转移方程为:
,其中
至此我们发现,我们需要一层循环遍历 j,一层循环遍历 k,还需要一次循环遍历 i。至此我们发现算法的时间复杂度在O(),当然面对这一道题目毛估估是可以过关的。因为 n 最大也就200。
这一段代码符合常理,也好编写。所以,我们不做展示。
接下来,我们经行优化。在遍历寻找的最小位置的时候,我们发现:如果第 i-1 行的最小值位置为 pos,那么除了 dp[i][pos] 外,其他列的最小值都应该由该位置转移而来。那么dp[i][pos]就应该从第 i-1 行第2小的位置转移而来。
基于此,我们可以撤销遍历k的循环,从而使用 first_sum,first_pos,second_sum来代替。注意第2小的位置我们无需关心,因为一定不会跟第1小的位置相同。
因为最后的答案就是第 i 行的 first_sum。所以我们在这里还可以撤销dp数组的额外空间。
AC代码:
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& grid) {
int n = grid.size();
int first_sum = 0, first_pos = -1, second_sum = 0;//初始化不对第 0 行的值有影响即可
for (int i = 0; i < n; ++i) {
int cur_fs = INT_MAX, cur_fp = -1, cur_ss = INT_MAX;//寻找当前的前两个小值
for (int j = 0; j < n; ++j) {
int cur_sum = (j == first_pos? second_sum: first_sum) + grid[i][j];
if (cur_sum < cur_fs) {
cur_ss = cur_fs;
cur_fs = cur_sum;
cur_fp = j;
}
else if (cur_sum < cur_ss) {
cur_ss = cur_sum;
}
}
//更新first_sum, first_pos, second_sum值
first_sum = cur_fs;
first_pos = cur_fp;
second_sum = cur_ss;
}
return first_sum;//返回第 n - 1行的最小值
}
};