LeetCode简易题解--120

题目描述:给出一个数字三角形,求出从上到下的数字之和最小的路径。一个数字只能通往下一层与它相邻的两个数字。

解法一

这道题目的想法很简单:

  • 从左到右,从上到下遍历矩阵,每次遍历到一个值,dp[i][j]表示从第一层到目前这个值(第i层第j个)的最小路径。
  • 每次遍历,由于上一层的一个数字只能通往下一层与它相邻的两个数字,因此在更新dp数组时,只需考虑上一层的两个值即可:dp[i][j] += min(dp[i-1][j-1], dp[i-1][j]).
  • 要注意边界的情况。对每行的第一个元素,dp[i-1][j-1]不存在:dp[i][0] += dp[i-1][0]。对每行的最后一个元素,dp[i-1][j]不存在:dp[i][j] += dp[i-1][j-1]

代码如下:

class Solution {
public:
    int min(vector<vector<int>>& triangle, int i, int j) {
        if (triangle[i - 1].size() <= j)
            return triangle[i - 1][j - 1];
        return triangle[i - 1][j] < triangle[i - 1][j - 1] ?
                triangle[i - 1][j] :
                triangle[i - 1][j - 1];
    }
    int minimumTotal(vector<vector<int>>& triangle) {
        int rows = triangle.size();
        for (int i = 1; i < rows; ++i) {
            triangle[i][0] += triangle[i - 1][0];
        }
        for (int i = 1; i < rows; ++i) {
            for (int j = 1; j <= i; ++j) {
                triangle[i][j] += min(triangle, i, j);
            }
        }
        int res = 0xffffff;
        for (int i = 0; i < rows; ++i) {
            if (res > triangle[rows - 1][i])
                res = triangle[rows - 1][i];
        }
        return res;
    }
};

解法二

解法二本质上和解法一是一样的。不同之处在于,解法一的空间复杂度为O(n^2);而解法二的空间复杂度为O(n)。
dp[j]表示到某一层的第j个数字的最小路径的值。
实现方法为:将解法一的从左到右的循环改为从右到左。
在某一层的遍历开始前,dp数组保存着上一层的结果。每一层的值要在上一层的基础上获得,而在计算到triangle[i][j]的最小路径时,dp[j],dp[j-1]就是所需要的上一层的两个结果。从右向左求值,保证了每次计算的时候,dp[j],dp[j-1]确实就是我们想要的值。
例如,计算这一层的dp[5]时,要用到dp[5],dp[4],这时dp[5],dp[4]还是上一层的值;计算结束后,dp[5]更新为这一层的值,但是没有关系,因为接下来计算dp[4]时,已经不需要用到dp[5]的值了,所需要的dp[4],dp[3]依旧是上一层的值。

边界的情况与解法一相同。

代码如下:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int rows = triangle.size();
        vector<int> dp(rows, INT_MAX);
        dp[0] = triangle[0][0];
        for (int i = 1; i < rows; ++i) {
            for (int j = i; j > 0; --j) {
                dp[j] = triangle[i][j] + min(dp[j], dp[j - 1]);
            }
            dp[0] += triangle[i][0];
        }
        int res = 0xffffff;
        for (int i = 0; i < rows; ++i) {
            if (res > dp[i])
                res = dp[i];
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值