Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
解题分析:
此题使用DP解决最优化为题,直接复用triangle数组,我们希望一层一层的累加下来,从而使得 triangle[i][j] 是从最顶层到 (i, j) 位置的最小路径和,那么我们如何得到状态转移方程呢?其实也不难,因为每个结点能往下走的只有跟它相邻的两个数字,那么每个位置 (i, j) 也就只能从上层跟它相邻的两个位置过来,也就是 (i-1, j-1) 和 (i-1, j) 这两个位置,那么状态转移方程为:
triangle[i][j] = min(triangle[i - 1][j - 1], triangle[i - 1][j])
我们从第二行开始更新,注意两边的数字直接赋值上一行的边界值,那么最终我们只要在最底层找出值最小的数字,就是全局最小的路径和啦。
代码:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle)
{
if(triangle.size() == 1)
return triangle[0][0];
for(int row = 0; row < triangle.size(); row++)
{
for(int col = 0; col < triangle[row].size(); col++)
{
if(row - 1 < 0)
{
continue;
}
if(col-1 < 0)
{
triangle[row][col] += triangle[row-1][col];
}
else if(col >= triangle[row-1].size())
{
triangle[row][col] += triangle[row-1][col-1];
}
else
{
triangle[row][col] += min(triangle[row-1][col],triangle[row-1][col-1]);
}
}
}
int min = 0xffff;
int maxRow = triangle.size()-1;
for(int i = 0; i < triangle[maxRow].size(); i++)
{
if(triangle[maxRow][i] < min)
{
min = triangle[maxRow][i];
}
}
return min;
}
};
解题思路二:
使用一维数组dp[col], 这种方法复制了三角形最后一行,作为用来更新的一位数组。然后逐个遍历这个DP数组,对于每个数字,和它之后的元素比较选择较小的再加上面一行相邻位置的元素做为新的元素,然后一层一层的向上扫描,扫描完第一个元素即为所求。
代码:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> dp(triangle.back());
for (int i = (int)triangle.size() - 2; i >= 0; --i) {
for (int j = 0; j <= i; ++j) {
dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j];
}
}
return dp[0];
}
};
引用:
LeetCode - 120. Traingle & Hdu - 2084. 数塔问题(简单dp)
来源:CSDN
作者:xuchenhuics
链接:https://blog.csdn.net/xuchenhuics/article/details/103844145