120. 三角形最小路徑和

題目描述

給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。算法

例如,給定三角形(用二維向量triangle表示):數組

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

說明:

若是你能夠只使用 O(n) 的額外空間(n 爲三角形的總行數)來解決這個問題,那麼你的算法會很加分。bash

算法

利用動態規劃求解自上向下的三角形路徑和,難點在於要求額外的空間複雜度位O(n)。那麼不妨利用傳入的二維向量做爲一個媒介更新dp數組。spa

若是沒有複雜度要求的話,能夠開一個二維數組dp[n][n],n是三角形的行數。從上至下的更新狀況下所示:code

[
      [2],
     [5,6],
   [11,10,13],
  [15,11,18,13]
]

最終返回的是dp的最後一行中最小的那個數。io

如今要求空間複雜度爲O(n),即最多隻能開一個一維數組dp[n],n是三角形的行數。能夠將dp中的數加到triangle中對應的行,最後再將triangle中對應的該行從新保存回dp。一位triangle一行最多保存n個數,因此dp[n]已經夠用。詳細註釋在代碼中給出。class

代碼

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int size = triangle.size();
        // 邊界條件,若triangle僅有一行,直接返回第一行的該數便可
        if(size == 1)
            return triangle[0][0];
        
        // 開dp數組
        int dp[size];
        dp[0] = triangle[0][0];
        
        // 自三角形的第二行從上到下遍歷,體如今下標爲i=1。由於二維向量由i=0開始,i=0表明第一行,這裏不要搞混了。
        for (int i = 1; i < size; i++)
        {
            // 從前日後遍歷triangle[i]這個向量,並用已經保存的dp數組更新triangle[i]
            for (int j = 0; j <= i; j++)
            {
                if(j == 0)
                    triangle[i][j] += dp[j];
                else if(j == i)
                    triangle[i][j] += dp[j-1];
                else
                    triangle[i][j] += min(dp[j], dp[j-1]);
            }
            
            // 從新保存回dp數組,以用來更新三角形的下一行
            for (int j = 0; j < triangle[i].size(); j++)
                dp[j] = triangle[i][j];
        }
        // 取dp中最小的那個數返回
        int _min = 99999999;
        for (int j = 0; j < size; j++)
            if(_min > dp[j])
                _min = dp[j];
        return _min;
    }
};
相關文章
相關標籤/搜索