1. 程式人生 > >動態規劃] 120. Triangle

動態規劃] 120. Triangle

1 題目

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.

2 題目分析

  • 本題資料來源很像一棵樹,為了搜尋最短路徑,可以使用DFS。但是在搜尋的過程中,尋求到達某一中間點k的最短路徑需要知道到達其父節點的最短路徑,根據題目要求,到達k的最短路徑可能是從k的兩個父節點引出的,設m是與k相鄰的節點,那麼m與k共享可能引出最短路徑的父節點,所以如果單純使用DFS,在求k與m的最短路徑時,其父節點上的最短路徑被求了兩次,這就導致了重疊子問題

  • 這個問題中,如果知道了節點k的兩個子節點到樹根的最短路徑,節點k應該包含在值小的子路徑中,即:

    minPath = min(P1,P2) + k其中P1,P2`是k的兩個子節點的最短路徑,這是這個問題的最優子結構,即可以由子問題推匯出父問題的解

  • 最後一行每一個節點的最短路徑必須包含節點自身。

可以得出以下虛擬碼:

minPath 為一個長度為n的列表,初始化為最後一行的值
i in 從倒數第二行到第一行:
  j in 每一行的從左到右:
    minPath[i] = min(minPath[j], minPath[j+1]) + triangle[i][j]
minPath[0
]就是要求的最短路徑的值

3 Python原始碼

# -*- encoding:utf-8 -*-

class Solution:
    def minimumTotal(self, triangle):
        """
        :type triangle: List[List[int]]
        :rtype: int
        """
        minSum = triangle[-1]
        for i in range(len(triangle)-2,-1,-1):
            for j in range(0,i+1):
                minSum[j] = triangle[i][j] + min(minSum[j], minSum[j+1])
        return minSum[0]


def main():
    triangle = [ 
                  [2],\
                 [3,4],\
                [6,5,7],\
               [4,1,8,3] \
             ]
    solution = Solution()
    print(solution.minimumTotal(triangle))

if __name__ == '__main__':
    main()