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.

思路

矩阵型动态规划问题

有两种方法:自上而下和自下而上

方法一:自下而上

从最底层到(i, j)所用的最短距离等于该点左下角(i+1, j)和右下角(i+1, j+1)之间的最小值加上当前点的值

triangle[i][j] += min(triangle[i+1][j] + triangle[i+1][j+1])

最终的值是: triangle[0][0]

方法二:自上而下

从顶层到(i, j)所用的最短距离等于该点左下角(i+1, j)和右下角(i+1, j+1)之间的最小值加上当前点的值

triangle[i][j] += min(triangle[i-1][j-1] + triangle[i-1][j])

注意:下一行的首尾分别只能和上一行的首尾相邻,其他元素可以和上一行的两个元素相邻

最终的值是:最后一行的最小值

C++11

方法一:自下而上

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        // 从倒数第二行开始计算
        for (int i = triangle.size() - 2; i >= 0; --i) 
            // 当前行元素的个数等于i+1
            for (int j = 0; j <= i; ++j)
                triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1]);
        return triangle[0][0];
    }
};

方法二:自上而下

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        vector<int> cache;  // 存储前一行计算后的值
        for (auto &cur_v : triangle) {
            // 当前行首尾直接加上上一行的首尾
            if (!cache.empty()) {
                cur_v.front() += cache.front();
                cur_v.back() += cache.back();
            }
            for (size_t i = 1; i < cache.size(); ++i)
                cur_v[i] += min(cache.at(i-1), cache.at(i));
            // 当前行计算完后赋值给cache,便于下一次迭代计算
            cache = cur_v; 
        }
        // 返回最后一行计算后的最小值
        return *min_element(cache.cbegin(), cache.cend());
    }
};

results matching ""

    No results matching ""