代码改变世界

[LeetCode] 120. Triangle _Medium tag: Dynamic Programming

2019-04-22 04:24  Johnson_强生仔仔  阅读(220)  评论(0编辑  收藏  举报

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.

 

可以用DFS中的divide and conquer来去计算,此时会有O(2^h) 的复杂度,所以可以加上memorize的array去优化时间复杂度。最后时间复杂度为 O(h^2)

同时通过 f[x][y] = nums[x][y] + min(f[x + 1][y], f[x + 1][y + 1])  来得到for loop去循环来得到的结果,其实就是上面那种做法用for loop来写而已。时间复杂度为 O(h^2)

 

0) brute force , T: O(2 ^ h), Time limit Exceeded

class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        return self.dfs(triangle, 0 , 0)
    
    def dfs(self, triangle: List[List[int]], i: int, j: int):
        if i == len(triangle) - 1:
            return triangle[i][j]
        left = self.dfs(triangle, i + 1, j)
        right = self.dfs(triangle, i + 1, j + 1)
        return triangle[i][j] + min(left, right)

 

 

1) 利用DFS, Divide and conquer

class Solution:
    def triangle(self, nums):
        if not nums or len(nums[0]) == 0:
            return 0
        mem = [[None]*len(nums) for _ in range(len(nums))]
        def helper(nums, x, y):
            if x == len(nums) - 1:
                return nums[x][y]
            if mem[x][y] is not None:
                return mem[x][y]
            left = helper(nums, x + 1, y)
            right = helper(nums, x + 1, y + 1)
            mem[x][y] = nums[x][y] + min(left, right)
            return mem[x][y]
        return helper(nums, 0, 0)

 

2) 利用for loop并且memorize(#using just O(n) space)

more compact

class Solution(object):
    def minimumTotal(self, nums):
        """
        :type triangle: List[List[int]]
        :rtype: int
        """
        n = len(nums)
        if n == 0: return 0
        mem = [[0] * n for _ in range(2)]
        for i in range(n - 1, -1, -1):
            for j in range(len(nums[i])):
                mem[i%2][j] = nums[i][j] if i == n - 1 else nums[i][j] + min(mem[(i + 1)%2][j], mem[(i + 1)%2][j + 1])
        return mem[0][0]