LeetCode练习题120. Triangle

这是一篇关于LeetCode第120题的解析,题目要求找到从三角形顶部到底部的最小路径和。文章讨论了使用递归和动态规划两种方法解决此问题,指出递归方法在处理大型数据时可能会导致Time Limit Exceeded,而动态规划是此题的正确解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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.

 

递归方法

这道题的数据结构很像二叉树的结构,我们可以用递归遍历二叉树的思想来遍历所有的可能的路径,以求出最小的路径权重和。

定义一个辅助的递归函数 int myRecursion(vector<vector<int>>& triangle, int i, int j),这个第一个参数为原三角形,第二和第三个参数(i,j)代表当前遍历到的三角形的节点位置,返回值为以当前节点(i,j)出发到底层的最小路径权重和。

所以我们从(0,0)节点处开始调用myRecursion,在myRecursion函数内部,分别计算(i,j)节点相邻两条路径的最小路径权重和,然后取两者的最小值加上本节点(i,j)的权重,作为以当前节点(i,j)出发到底层的最小路径权重和。

代码如下:

class Solution {
public:
    int myRecursion(vector<vector<int>>& triangle, int i, int j) {
        int row = triangle.size();
        int col = triangle[i].size();
        int result1;
        int result2;

        if (i == row - 1) {
            return triangle[i][j];
        }
        else if (i < row - 1) {
            result1 = myRecursion(triangle, i + 1, j) + triangle[i][j];
            result2 = myRecursion(triangle, i + 1, j + 1) + triangle[i][j];
            return result1 < result2 ? result1 : result2;
        }

    }

    int minimumTotal(vector<vector<int>>& triangle) {
        return myRecursion(triangle, 0, 0);
    }
};

递归的方法从正确性来看是正确的,但在LeetCode中测试时只能通过45/46个测例,最后一个测例不通过。原因是最后一个测例三角形的元素太多,而递归方法的开销较大,出现了Time Limit Exceeded错误。所以在这道题里面,递归方法不一定适用。

 

动态规划方法

动态规划方法是正确的解决办法。

利用动态规划的方法计算,按照题目的三角形数据,计算过程如下:

生命一个int类型数组all_dist,对于原来的三角形,遍历到第二层时,有 2+3=5和2+4=6,我们要把遍历到当前层各节点所经历的最小权重和保存到all_dist中,所以all_dist保存当前层的计算结果[5,6]。

接下来,当前层为[6,5,7]。对于当前行中的每一个元素,计算当前元素权重与上一行中相邻的2个元素权重和的最小值,然后把这个最小值更新到当前元素对应all_dist数组的位置。不断进行下去,直到最后一行为止。

代码如下:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int row = triangle.size();
        vector<int> all_dist(1000, 0);
        int result = 0;

        all_dist[0] = triangle[0][0];

        for (int i = 1; i < row; i++) {
            vector<int> temp_all_dist(all_dist);
            for (int j = 1; j < i; j++) {
                all_dist[j] = temp_all_dist[j] + triangle[i][j] < temp_all_dist[j - 1] + triangle[i][j] ?
                    temp_all_dist[j] + triangle[i][j] : temp_all_dist[j - 1] + triangle[i][j];
            }
            all_dist[0] = temp_all_dist[0] + triangle[i][0];
            all_dist[i] = temp_all_dist[i - 1] + triangle[i][i];
        }

        result = all_dist[0];
        for (int i = 1; i < row; i++) {
            result = result < all_dist[i] ? result : all_dist[i];
        }
        return result;
    }
};

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值