120 三角形最小路径和

本文最后更新于:2022年4月9日 中午

给定一个三角形 triangle ,找出自顶向下的最小路径和。

每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 ii + 1

示例 1:

1
2
3
4
5
6
7
8
输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出:11
解释:如下面简图所示:
2
3 4
6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

示例 2:

1
2
输入:triangle = [[-10]]
输出:-10

提示:

  • 1 <= triangle.length <= 200
  • triangle[0].length == 1
  • triangle[i].length == triangle[i - 1].length + 1
  • -104 <= triangle[i][j] <= 104

进阶:

  • 你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题吗?

Solution

参考 @liuyubobobo 、**@LeetCode官方**

动态规划

  • 自底向上

image-20210129151203588

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// @lc code=start
class Solution {
private:
// 自底向上
int go(const vector<vector<int>>& triangle, int i, int j,
vector<vector<int>>& dp){
if(dp[i][j] != -1)
return dp[i][j];
if(i==0)
return dp[i][j] = triangle[i][j];
if(j==0)
return dp[i][j] = triangle[i][j] + go(triangle, i-1, 0, dp);
if(j==i)
return dp[i][j] = triangle[i][j] + go(triangle, i-1, j-1, dp);

return dp[i][j] = triangle[i][j] + min(go(triangle, i-1, j-1, dp),
go(triangle, i-1, j, dp));
}

public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<vector<int>> dp(n, vector<int>(n, -1));
for(int i=0; i<n; ++i){
go(triangle, n-1, i, dp);
}
return *min_element(dp[n-1].begin(), dp[n-1].end());
}
};
// @lc code=end
  • 自底向上,记忆优化搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<vector<int>> dp(n, vector<int>(n, -1));
dp[0][0] = triangle[0][0];

for(int i=1; i<n; ++i){
dp[i][0] = dp[i-1][0]+triangle[i][0];
for(int j=1; j<i; ++j)
dp[i][j] = min(dp[i-1][j-1], dp[i-1][j])+triangle[i][j];
dp[i][i] = dp[i-1][i-1]+triangle[i][i];
}
return *min_element(dp[n-1].begin(), dp[n-1].end());
}
};
  • 状态压缩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 自底向上
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<int> dp(n+1, 0);

for(int i=n-1; i>=0; --i){ // 最后一行开始
for(int j=0; j<triangle[i].size(); ++j){ // 第一列开始
dp[j] = min(dp[j], dp[j+1]) +triangle[i][j];
}
}
return dp[0];
}
};

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!