LeetCode練習題120. Triangle
題目
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is
11
(i.e., 2 + 3 + 5 + 1 = 11).Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
遞迴方法
這道題的資料結構很像二叉樹的結構,我們可以用遞迴遍歷二叉樹的思想來遍歷所有的可能的路徑,以求出最小的路徑權重和。
定義一個輔助的遞迴函式 int myRecursion(vector<vector<int>>& triangle, int i, int j),這個第一個引數為原三角形,第二和第三個引數(i,j)代表當前遍歷到的三角形的節點位置,返回值為以當前節點(i,j)出發到底層的最小路徑權重和。
所以我們從(0,0)節點處開始呼叫myRecursion,在myRecursion函式內部,分別計算(i,j)節點相鄰兩條路徑的最小路徑權重和,然後取兩者的最小值加上本節點(i,j)的權重,作為以當前節點(i,j)出發到底層的最小路徑權重和。
程式碼如下:
class Solution { public: int myRecursion(vector<vector<int>>& triangle, int i, int j) { int row = triangle.size(); int col = triangle[i].size(); int result1; int result2; if (i == row - 1) { return triangle[i][j]; } else if (i < row - 1) { result1 = myRecursion(triangle, i + 1, j) + triangle[i][j]; result2 = myRecursion(triangle, i + 1, j + 1) + triangle[i][j]; return result1 < result2 ? result1 : result2; } } int minimumTotal(vector<vector<int>>& triangle) { return myRecursion(triangle, 0, 0); } };
遞迴的方法從正確性來看是正確的,但在LeetCode中測試時只能通過45/46個測例,最後一個測例不通過。原因是最後一個測例三角形的元素太多,而遞迴方法的開銷較大,出現了Time Limit Exceeded錯誤。所以在這道題裡面,遞迴方法不一定適用。
動態規劃方法
動態規劃方法是正確的解決辦法。
利用動態規劃的方法計算,按照題目的三角形資料,計算過程如下:
生命一個int型別陣列all_dist,對於原來的三角形,遍歷到第二層時,有 2+3=5和2+4=6,我們要把遍歷到當前層各節點所經歷的最小權重和儲存到all_dist中,所以all_dist儲存當前層的計算結果[5,6]。
接下來,當前層為[6,5,7]。對於當前行中的每一個元素,計算當前元素權重與上一行中相鄰的2個元素權重和的最小值,然後把這個最小值更新到當前元素對應all_dist陣列的位置。不斷進行下去,直到最後一行為止。
程式碼如下:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int row = triangle.size();
vector<int> all_dist(1000, 0);
int result = 0;
all_dist[0] = triangle[0][0];
for (int i = 1; i < row; i++) {
vector<int> temp_all_dist(all_dist);
for (int j = 1; j < i; j++) {
all_dist[j] = temp_all_dist[j] + triangle[i][j] < temp_all_dist[j - 1] + triangle[i][j] ?
temp_all_dist[j] + triangle[i][j] : temp_all_dist[j - 1] + triangle[i][j];
}
all_dist[0] = temp_all_dist[0] + triangle[i][0];
all_dist[i] = temp_all_dist[i - 1] + triangle[i][i];
}
result = all_dist[0];
for (int i = 1; i < row; i++) {
result = result < all_dist[i] ? result : all_dist[i];
}
return result;
}
};