题目:
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, wheren is the total number of rows in the triangle.
解法一:两个vector交替更新
我们需要扫描此二维数组,得到sum数组。
对于第i行:我们有
sum[i][0] = sum[i-1][0]+a[i][0]; j=0
sum[i][j] = Min( sum[i-1][j-1]+a[i][j] , sum[i-1][j]+a[i][j] ); 0<j<i
sum[i][i] = sum[i-1][i-1]+a[i][i]; j=i;
如此可得到结果。
当然我们可以申请一个二维的vector来存储sum,将sum的最后一行的最小值返回,即为结果。
但是题目要求需要 O(n) 的空间。所以我们考虑用两个 vector 来交替实现。
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(triangle.size()<=0)
return 0;
vector<int> myvector, tmpvector;
myvector.push_back(triangle[0][0]);
for(int i=1;i<triangle.size();i++)
{
tmpvector.push_back(myvector[0]+triangle[i][0]);
for(int j=1;j<i;j++)
{
int left = myvector[j-1]+triangle[i][j];
int right = myvector[j]+triangle[i][j];
int min = (left<right)?left:right;
tmpvector.push_back(min);
}
tmpvector.push_back(myvector[i-1]+triangle[i][i]);
myvector = tmpvector;
tmpvector.clear();
}
int minsum = myvector[0];
for(int i=0;i<myvector.size();i++)
if(myvector[i]<=minsum)
minsum = myvector[i];
return minsum;
}
};
Program Runtime: 12 milli secs
解法二:单个vector逐步更新
如果用一个一维数组来存储,可知 由第i-1行得到第i行:
sum[0] = sum[0]+a[i][0]; j=0
sum[j] = Min( sum[j-1]+a[i][j] , sum[j]+a[i][j] ); 0<j<i
sum[i] = sum[i-1]+a[i][i]; j=i;
代码如下:
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(triangle.size()<=0)
return 0;
vector<int> myvector(triangle[triangle.size()-1].size());
myvector[0] = triangle[0][0];
for(int i=1;i<triangle.size();i++)
{
myvector[0] = myvector[0]+triangle[i][0];
for(int j=1;j<i;j++)
myvector[j] = min(myvector[j-1],myvector[j])+triangle[i][j];
myvector[i] = myvector[i-1]+triangle[i][i];
}
int minsum = myvector[0];
for(int i=0;i<myvector.size();i++)
minsum = min(minsum,myvector[i]);
return minsum;
}
};
我们会发现一个问题,部分结果是不对的,
因为 sum[j] = Min( sum[j-1]+a[i][j] , sum[j]+a[i][j] ); 这行代码中,我们会用到刚刚更新后的 sum[j-1] ,导致结果不对。
所以我们要考虑从后往前生成第i 行,而不是从前往后。
正确解法如下:
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(triangle.size()<=0)
return 0;
vector<int> myvector(triangle[triangle.size()-1].size());
myvector[0] = triangle[0][0];
for(int i=1;i<triangle.size();i++)
{
myvector[i] = myvector[i-1]+triangle[i][i];
for(int j=i-1;j>=1;j--)
myvector[j] = min(myvector[j-1],myvector[j])+triangle[i][j];
myvector[0] = myvector[0]+triangle[i][0];
}
int minsum = myvector[0];
for(int i=0;i<myvector.size();i++)
minsum = min(minsum,myvector[i]);
return minsum;
}
};
可见区别仅在 第二层 For 循环中。这次得到了理想的时间和空间效率。