(5)三角矩阵求最小路径

三角矩阵问题

问题描述:

给定一个三角矩阵,求从上到下和最小的一条路径,每次只能移动到下一行相邻的数字
[
[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];
    }
点赞