Leetcode120 Triangle (DP经典题)

本文讨论了如何在给定三角形数组中找到从顶点到底端的最小路径和,提供了三种不同的动态规划解法,包括直接DP、滚动数组优化和01背包空间优化技巧。
  1. Triangle
    Medium
    8.7K
    503
    Companies
    Given a triangle array, return the minimum path sum from top to bottom.

For each step, you may move to an adjacent number of the row below. More formally, if you are on index i on the current row, you may move to either index i or index i + 1 on the next row.

Example 1:

Input: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
Output: 11
Explanation: The triangle looks like:
2
3 4
6 5 7
4 1 8 3
The minimum path sum from top to bottom is 2 + 3 + 5 + 1 = 11 (underlined above).
Example 2:

Input: triangle = [[-10]]
Output: -10

Constraints:

1 <= triangle.length <= 200
triangle[0].length == 1
triangle[i].length == triangle[i - 1].length + 1
-104 <= triangle[i][j] <= 104

Follow up: Could you do this using only O(n) extra space, where n is the total number of rows in the triangle?

解法1:最直接的DP。

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int n = triangle.size();
        if (n == 0) return 0;
        
        vector<vector<int>> dp(n, vector<int>(n, 0));
        dp[0][0] = triangle[0][0];
        //line i (start from 0) has i + 1 numbers
        for (int i = 1; i < n; i++) {
            dp[i][0] = dp[i - 1][0] + triangle[i][0];
            dp[i][i] = dp[i - 1][i - 1] + triangle[i][i];
            for (int j = 1; j < i; j++) {
                dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j];
            }
        }
        int res = dp[n - 1][0];
        for (int i = 1; i < n; i++) {
            if (res > dp[n - 1][i]) res = dp[n - 1][i];
        }
        return res;
    }
};

解法2:滚动数组实现空间优化

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int n = triangle.size();
        if (n == 0) return 0;
        
        vector<vector<int>> dp(2, vector<int>(n, 0));
        dp[0][0] = triangle[0][0];
        //line i (start from 0) has i + 1 numbers
        for (int i = 1; i < n; i++) {
            dp[i % 2][0] = dp[(i - 1) % 2][0] + triangle[i][0];
            dp[i % 2][i] = dp[(i - 1) % 2][i - 1] + triangle[i][i];
            for (int j = 1; j < i; j++) {
                dp[i % 2][j] = min(dp[(i - 1) % 2][j - 1], dp[(i - 1) % 2][j]) + triangle[i][j];
            }
        }
        int res = dp[(n - 1) % 2][0];
        for (int i = 1; i < n; i++) {
            if (res > dp[(n - 1) % 2][i]) res = dp[(n - 1) % 2][i];
        }
        return res;
    }
};

解3:
类似01背包的空间优化。注意j的顺序是从大到小。

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int n = triangle.size();
        if (n == 0) return 0;
        
        vector<int> dp(n, INT_MIN);
        dp[0] = triangle[0][0];
        //line i (start from 0) has i + 1 numbers
        for (int i = 1; i < n; i++) {
            // j 的处理是从大到小 
            dp[i] = dp[i - 1] + triangle[i][i];           
            for (int j = i - 1; j > 0; j--) {
                dp[j] = min(dp[j - 1], dp[j]) + triangle[i][j];
            }
            dp[0] = dp[0] + triangle[i][0]; 
        }
        int res = dp[0];
        for (int i = 1; i < n; i++) {
            if (res > dp[i]) res = dp[i];
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值