1. 程式人生 > >LeetCode練習題120. Triangle

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;
    }
};