Leetcode 120. 三角形最小路径和

Leetcode 120. 三角形最小路径和

题目描述

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

解题思路

动态规划,用 d p [ i ] [ j ] dp[i][j] dp[i][j]表示从顶点到达 ( i , j ) (i, j) (i,j)点的最短路径和。状态转移方程如下:
d p [ i ] [ j ] = { t r i a n g l e [ i ] [ j ]                                                                     i = 0 t r i a n g l e [ i ] [ j ] + d p [ i − 1 ] [ j ]                                             j = 0 t r i a n g l e [ i ] [ j ] + d p [ i − 1 ] [ j − 1 ]                                      j = t r i a n g l e [ i ] . l e n g t h − 1 t r i a n g l e [ i ] [ j ] + m i n { d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − 1 ] }      t r i a n g l e [ i ] . l e n g t h − 1 > j > 0 dp[i][j]= \left \{ \begin{array}{lr} triangle[i][j]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ i=0\\ triangle[i][j]+dp[i-1][j]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j=0\\ triangle[i][j]+dp[i-1][j-1]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j=triangle[i].length-1\\ triangle[i][j]+min\{dp[i-1][j],dp[i-1][j-1]\}\ \ \ \ triangle[i].length-1>j>0 \end{array} \right . dp[i][j]=triangle[i][j]                                                                   i=0triangle[i][j]+dp[i1][j]                                           j=0triangle[i][j]+dp[i1][j1]                                    j=triangle[i].length1triangle[i][j]+min{dp[i1][j],dp[i1][j1]}    triangle[i].length1>j>0
在这里插入图片描述
可以看出来,更新第 i i i行只需要用到第 i − 1 i-1 i1行,所以可以进一步优化空间。
d p [ j ] dp[j] dp[j]表示从顶点到达 ( i , j ) (i, j) (i,j)点的最短路径和,优化之后的公式如下:
d p [ j ] = { t r i a n g l e [ i ] [ j ]                                               i = 0 t r i a n g l e [ i ] [ j ] + d p [ j ]                                  j = 0 t r i a n g l e [ i ] [ j ] + d p [ j − 1 ]                           j = t r i a n g l e [ i ] . l e n g t h − 1 t r i a n g l e [ i ] [ j ] + m i n { d p [ j ] , d p [ j − 1 ] }      t r i a n g l e [ i ] . l e n g t h − 1 > j > 0 dp[j]= \left \{ \begin{array}{lr} triangle[i][j]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ i=0\\ triangle[i][j]+dp[j]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j=0\\ triangle[i][j]+dp[j-1]\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j=triangle[i].length-1\\ triangle[i][j]+min\{dp[j],dp[j-1]\}\ \ \ \ triangle[i].length-1>j>0 \end{array} \right . dp[j]=triangle[i][j]                                             i=0triangle[i][j]+dp[j]                                j=0triangle[i][j]+dp[j1]                         j=triangle[i].length1triangle[i][j]+min{dp[j],dp[j1]}    triangle[i].length1>j>0
其中, i = { 0 , 1 , 2 , . . . , n − 1 } i=\{0,1,2,...,n-1\} i={0,1,2,...,n1}
j = { t r i a n g l e [ i ] . l e n g t h − 1 , t r i a n g l e [ i ] . l e n g t h − 2 , . . . , 0 } j=\{triangle[i].length-1, triangle[i].length-2,...,0\} j={triangle[i].length1,triangle[i].length2,...,0}
注意, j j j必须是降序,这是因为求 d p [ j ] dp[j] dp[j]需要用到 d p [ j − 1 ] dp[j-1] dp[j1]。如果求 d p [ j ] dp[j] dp[j]需要用到 d p [ j + 1 ] dp[j+1] dp[j+1],则 j j j需要是升序。

代码实现

不带空间优化

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int dp[1050][1050] = {0};
        int n = triangle.size();
        if (n == 0) return 0;
        if (triangle[0].size() == 0) return 0;
        
        dp[0][0] = triangle[0][0];
        
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < triangle[i].size(); j++) {
                if (j == 0) {
                    dp[i][j] = dp[i-1][j] + triangle[i][j];
                }
                else if (j == triangle[i].size()-1) {
                    dp[i][j] = dp[i-1][j-1] + triangle[i][j];
                }
                else {
                    dp[i][j] = triangle[i][j] + min(dp[i-1][j], dp[i-1][j-1]);
                }
            }
        }
        int ans = dp[n-1][0];
        for (int j = 1; j < triangle[n-1].size(); j++) {
            ans = min(ans, dp[n-1][j]);
        }
        return ans;
    }
};

空间优化

class Solution {
public:
    int minimumTotal(vector<vectot<int>>& triangle) {
        int dp[1050] = {0};
        int n = triangle.size();
        if (n == 0) return 0;
        if (triangle[0].size() == 0) return 0;
        
        dp[0] = triangle[0][0];
        
        for (int i = 1; i < n; i++) {
            for (int j = triangle[i].size()-1; j >= 0; j--) {
                if (j == 0) {
                    dp[j] = dp[j] + triangle[i][j];
                }
                else if (j == triangle[i].size()-1) {
                    dp[j] = dp[j-1] + triangle[i][j];
                }
                else {
                    dp[j] = triangle[i][j] + min(dp[j], dp[j-1]);
                }
            }
        }
        int ans = dp[0];
        for (int j = 1; j < triangle[n-1].size(); j++) {
            ans = min(ans, dp[j]);
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值