120.Triangle

题目描述

给出一个三角形(数据数组),找出从上往下的最小路径和。每一步只能移动到下一行中的相邻结点上。

比如,给你如下三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

则从上至下最小路径和为 11(即,2 + 3 + 5 + 1 = 11)

注意:

加分项:如果你可以只使用 O(n) 的额外空间(n是三角形的行数)。

我的解法——DP(AC)

  • Matrix DP:我们可以发现如下规律,当我们求解minimumi时,我们会用到minimumi+1和minimumi+1,但是当求解完所有minimum[i]之后minimum[i+1]就没有用处了。
  • 转移方程:
    • S[i]/[j] = min(S[i+1]/[j] + S[i+1]/[j+1]) +S[i]/[j]
    • 由于S[i]/[j]只与下一行的第j个元素和第j+1个元素相关,i的关系是固定的,因此我们可以省去这一维。开辟O(N)的数组,然后规划的时候使用S[j] = min(S[j+1], S[j]) +Triangle[i][j]就可以了。
  • 有两种解决方案,自顶向下或者自底向上
  • 复杂度O(n2)
  • 结果:Beat44.37%
  • 改进:在更新中间数组的时候注意。本题比较巧妙的地方在于,如果从上到下进行计算,更新中间数组比较麻烦,要用两个变量(下面第一种代码中pre 和cur)去记录当前的元素防止当前循环被更新后下一次循环就找不到了。如果从下到上进行计算,由于每行的大小在递减,所以正好可以直接在当前数组上进行更新。
class Solution:
    def minimumTotal(self, triangle):
        """
        :type triangle: List[List[int]]
        :rtype: int
        """
        
        m = len(triangle)
        n = len(triangle[m - 1]) if(m != 0) else 0
        dp = [0] * n
        
        if(m != 0 and n != 0):
            dp[0] = triangle[0][0]
        else:
            return 0
        
        for i in range(1,m):
            last = dp[0] # 记忆上一位防止被覆盖
            for j in range(i + 1):
                if(j == 0):
                    dp[j] = dp[j] + triangle[i][j]
                elif(j == i):
                    dp[j] = last + triangle[i][j]
                else:
                    templast = dp[j]
                    dp[j] = min(last,dp[j]) + triangle[i][j]
                    last = templast

        return min(dp)

参考答案

  • https://www.cnblogs.com/liujinhong/p/5551932.html