C++实现LeetCode(120.三角形)
admin
2023-05-03 00:01:35

[LeetCode] 120.Triangle 三角形

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.

这道题给了我们一个二维数组组成的三角形,让我们寻找一条自上而下的路径,使得路径和最短。那么那道题后还是先考虑下暴力破解,我们可以发现如果要遍历所有的路径的话,那可以是阶乘级的时间复杂度啊,OJ必灭之,趁早断了念想比较好。必须要优化时间复杂度啊,题目中给的例子很容易把人带偏,让人误以为贪婪算法可以解题,因为看题例子中的红色数组,在根数字2的下方选小的数字3,在3的下方选小的数字5,在5的下方选小的数字1,每次只要选下一层相邻的两个数字中较小的一个,似乎就能得到答案了。其实是不对的,贪婪算法可以带到了局部最小,但不能保证每次都带到全局最小,很有可能在其他的分支的底层的数字突然变的超级小,但是贪婪算法已经将其他所有分支剪掉了。所以为了保证我们能得到全局最小,动态规划Dynamic Programming还是不二之选啊。其实这道题和 Dungeon Game 非常的类似,都是用DP来求解的问题。那么其实我们可以不新建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>& triangle) {
        for (int i = 1; i < triangle.size(); ++i) {
            for (int j = 0; j < triangle[i].size(); ++j) {
                if (j == 0) {
                    triangle[i][j] += triangle[i - 1][j];
                } else if (j == triangle[i].size() - 1) {
                    triangle[i][j] += triangle[i - 1][j - 1];
                } else {
                    triangle[i][j] += min(triangle[i - 1][j - 1], triangle[i - 1][j]);
                }
            }
        }
        return *min_element(triangle.back().begin(), triangle.back().end());
    }
};

这种方法可以通过OJ,但是毕竟修改了原始数组triangle,并不是很理想的方法。在网上搜到一种更好的DP方法,这种方法复制了三角形最后一行,作为用来更新的一位数组。然后逐个遍历这个DP数组,对于每个数字,和它之后的元素比较选择较小的再加上面一行相邻位置的元素做为新的元素,然后一层一层的向上扫描,整个过程和冒泡排序的原理差不多,最后最小的元素都冒到前面,第一个元素即为所求。代码如下:

解法二: 

class Solution {
public:
    int minimumTotal(vector>& triangle) {
        vector 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];
    }
};

下面我们来看一个例子,对于输入数组:

     -1

    2   3

  1  -1  -3

5   3   -1   2

下面我们来看DP数组的变换过程(红色数字为每次dp数组中值改变的位置):

DP:5  3  -1  2

DP:4  3  -1  2

DP:4  -2  -1  2

DP:4  -2  -4  2

DP:0  -2  -4  2

DP:0  -1  -4  2

DP:-2  -1  -4  2

参考资料:

https://leetcode.com/problems/triangle/

https://www.zzm8.com/d/file/p/20210723180838104119/20210723180838104120

https://www.zzm8.com/d/file/p/20210723180838104127/20210723180838104128

到此这篇关于C++实现LeetCode(120.三角形)的文章就介绍到这了,更多相关C++实现三角形内容请搜索趣讯吧以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣讯吧!

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...