给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算***很加分。

使用二维数组的dp动态规划
dp[i][j]表示走到第i行j列的最小路径和
则转移方程 dp[i][j] = min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j]; 因为只能上一层的左和右两个元素可以走到[i][j]

需要考虑左右两侧的特俗情况 左右两侧只有固定的路径可达

// 216 三角形最小路径和
int minimumTotal(vector<vector<int>>& triangle) {
    int row = triangle.size();
    if(row==0) return 0;
    int col = triangle[row-1].size();

    vector<vector<int>> dp(row+1,vector<int> (col+1,INT32_MAX));
    dp[0][0] = triangle[0][0];

    int min_val = INT32_MAX;
    for(int i=1;i<row;i++){
        int col_ = triangle[i].size();
        for(int j=0;j<col_;j++){
            if(j==0) {
                dp[i][j] = dp[i-1][j]+triangle[i][j];
            }else if(j==col_-1){
                dp[i][j] = dp[i-1][j-1]+triangle[i][j];
            }else{
                dp[i][j] = min(dp[i-1][j-1],dp[i-1][j])+triangle[i][j];
            }
        }
    }
    for(int j=0;j<col;j++){
        min_val = min(min_val,dp[row-1][j]);
    }
    return min_val;
}


压缩状态方程空间O(n)

其实我们dp时候每次只用到上一层数据,如果我们倒着,从底向上可以优化成O(n)空间的

           |= triangle[n-1,c]       if n-1 is the last row. 
f(n-1, c) -|
           |= min{f(n,c) + triangle[n-1,c], f(n,c+1) + triangle[n-1,c]}


/*input
     *  {{2},
        {3,4},
       {6,5,7},
      {4,1,8,3}};
如果正序遍历的话, dp[j] = dp[j],dp[j-1] , 因为计算当前层 dp[j]需要用到 上一层的dp[j-1] 和 上一层的dp[j], 但是dp[j-1]已经更新为当前层的值, 
 而在计算当前层的dp[j]时,需要用到上一层的dp[j-1],但是计算当前层dp[j]前,已经更新过dp[j-1],可以从下面结果中看出

 * 2  \  \  \
 * 5  9  \  \
 * 11 14 21 \
 * 15 15 23 26
 * 
 * 倒序的话,dp[j] = min(dp[j],dp[j+1]), dp[j](当前层,更新) = dp[j](上一层.未更新),dp[j+1](上一层,未更新)
 * 计算当前层dp[j] 需要用到 上一层的dp[j] 和 dp[j+1], 相当于dp[j] 更新为当前层值,dp[j+1] 等待下一个迭代更新
 * 
 * */
int minimumTotal(vector<vector<int>>& triangle) {
    int row = triangle.size();
    if(row==0) return 0;

    vector<int> dp(row,0);
    for(int i=0;i<row;i++)
        dp[i] = triangle[row-1][i];

    for(int i=row-2;i>=0;i--){
    //
        for(int j=0;j<i+1;j++){
            dp[j] = min(dp[j],dp[j+1]) + triangle[i][j];
        }
    }
    return dp[0];
}