三角矩阵问题
问题描述:
给定一个三角矩阵,求从上到下和最小的一条路径,每次只能移动到下一行相邻的数字 [ [2], [3,4], [6,5,7], [4,1,8,3] ] 最小和为 11 ( 2 + 3 + 5 + 1 = 11) 题目链接:题目链接 |
(1)描述
F(i)(j) 表示从[0][0] 走到 [i][j] 最小路径和
(2)递归推演
例如位置为[2][1] 的元素 5 ,从上往下走的话,我们只有两种方案
一、从[1][0] 的元素 6 走到5
二、从[1][1] 的元素 4 走到5
我们当然是选取上面方案的最小方案
则有 F(i)(j) = min ( F(i – 1)(j – 1), F(i – 1)(j) ) + triangle[i][j];注意到三角形侧边位置只有一种方案
例如[2][0] 的元素6 和 [2][2] 的元素7
对于6 ,我们只能从[1][0] 3 走到 5
F(i)(0) = F(i – 1)(j) + triangle[i][j];
对于7 ,我们只能从[1][1] 4 走到 5
F(i)(i) =F(i – 1)(j – 1) + triangle[i][j];
(3)确定初值
F(0)(0) = triangle[0][0];
(4)返回值
返回最后一行的最小的一个值
min( F(len – 1)(i))
i = 0,1,2,……len – 1
(5)时间复杂度为O(N),空间复杂度为O(N)
代码实现
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle)
{
int len = triangle.size();
if(len <= 0) return 0;
int i = 0, j = 0;
vector<vector<int>> ret(len , vector<int>(len, 0));
//初始化第一一行
ret[0][0] = triangle[0][0];
//采取上向下的推演
for(i = 1;i < len;++i)
{
for(j = 0;j <= i; ++j)
{
if(j == 0) ret[i][j] = ret[i-1][j]+triangle[i][j];
else
if(j == i) ret[i][j] = ret[i-1][j - 1] + triangle[i][j];
else
ret[i][j] = min(ret[i-1][j -1],ret[i-1][j]) + triangle[i][j];
}
}
//最后在最底线一行中找一个最小的
int Min = ret[len - 1][0];
for(i = 0;i < len ;++i)
{
Min = min(ret[len - 1][i] , Min);
}
return Min;
}
};
思路二:
我们可以从下面往上面进行推演,这样的话,最顶层就是我们的结果数
F(i)(j) = min ( F(i +1)(j), F(i + 1)(j + 1) ) + triangle[i][j];
初值确定
最后一行的值我们直到就是tirangle里面对应的值
这个时候就不用考虑边界了,从下面一定有两条路通向该处
时间复杂度为O(N),空间复杂度为O(N)
代码实现
int minimumTotal(vector<vector<int> > &triangle)
{
int len = triangle.size();
if(len <= 0) return 0;
int i = 0, j = 0;
vector<vector<int>> ret(len , vector<int>(len, 0));
//处理最底下一行
for(i = 0;i < len ;++i)
{
ret[len - 1][i] = triangle[len - 1][i];
}
//采取由底向上的推演
for(i = len - 2;i >= 0;--i)
{
for(j = 0;j <= i; ++j)
{
ret[i][j] = min(ret[i+1][j],ret[i+1][j+1]) + triangle[i][j];
}
}
return ret[0][0];
}