給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。算法
例如,給定三角形(用二維向量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; } };