[LeetCode - 动态规划] 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()

你可能感兴趣的:(LeetCode)