朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux
目录
1. 题目解析
2. 算法原理讲解
2.1 状态表示
2.2 状态转移方程
2.3 初始化
2.4 填表顺序
2.5 返回值
3. 代码实现
4. 算法复杂度
1. 题目解析
LeetCode931.下降路径最小和:https://leetcode.cn/problems/minimum-falling-path-sum/description/https://leetcode.cn/problems/minimum-falling-path-sum/description/
931. 下降路径最小和
给你一个
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:
输入:matrix = [[-19,57],[-40,-5]] 输出:-59 解释:如图所示,为和最小的下降路径提示:
n == matrix.length == matrix[i].length
1 <= n <= 100
-100 <= matrix[i][j] <= 100
通过题目描述:首先这个方形二维数组是正方形,并且位于当前位置时,下一步只能走左下方、正下方、右下方走。
2. 算法原理讲解
本题我们采用动态规划的思想解题:路径问题的解题思路一般是以某一位置为结尾或者以某一位置为开始进行描述。
2.1 状态表示
根据题目要求:我们采用以某一位置为结尾进行描述;
以dp[i][j]为结尾 + 题目要求
所以dp[i][j]:表示到达[i][j]位置时,最小下降路径和
2.2 状态转移方程
根据题意,能到达[i, j]位置有三条路径,从左上方走下来、从正上方走下来、从右上方走下来,所以要从这三条路径里面选择最小的一条,假设从左上方[i-1, j-1]走下来路径和最小,那么走到[i-1, j-1]要保证最小路径和就呼应了我们的状态表示dp[i-1][j-1]。
左上方(x) dp[i-1][j-1]到达dp[i][j] => dp[i-1][j-1] + matrix[i][j]
到达dp[i][j]有三条路径 正上方(y) dp[i-1][j]到达dp[i][j] => dp[i-1][j-1] + matrix[i][j]
右上方(z) dp[i-1][j+1]到达dp[i][j] => dp[i-1][j-1] + matrix[i][j]
dp[i][j] = min(x, y, z) + matrix[i][j]
2.3 初始化
由于我们的状态转移方程需要用到左上方、右上方、正上方的数据,如果我们直接初始化:需要将最左边一列和最右边一列以及最上面一行初始化,这样初始化很麻烦:
所以我们在创建dp表时多开一行,多开两列
根据状态转移方程和状态表示,为了不影响后续填表的正确性,我们需要将第一行初始化为0,因为我们需要找三条路径中最小的,第一行都置为0不影响我们的填表,剩余两列初始化为INT_MAX也就是正无穷即可。
需要注意的时,填表的时候需要将matrix中的行和列减一,因为我们的dp表创建时就比原来大了。
2.4 填表顺序
根据状态转移方程可以看出填表顺序是从上往下
2.5 返回值
在计算到最后一行时,每个位置都代表了从上面到最小面的路径和,所以我们需要选出最小的进行返回
3. 代码实现
为了初始化方便,我们可以将所有的值先初始化为正无穷,然后再将第一行初始化为0即可。
class Solution { public:int minFallingPathSum(vector<vector<int>>& matrix) {int n = matrix.size();// 创建dp表vector<vector<int>> dp(n + 1, vector<int>(n + 2, INT_MAX)); // 初始化for(int j = 0; j<=n;j++) dp[0][j] = 0;// 填表for(int i = 1; i <= n; i++)for(int j = 1; j<= n; j++)dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i - 1][j + 1])) + matrix[i - 1][j - 1];int result = INT_MAX; // 获取最后一行的最小路径和for(int i = 1; i <= n + 1; i++)result = min(result, dp[n][i]);return result;} };
4. 算法复杂度
两层for循环:时间复杂度0(N^2)
二维dp表: 空间复杂度O(N^2)
朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!