给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
法1):
本题典型的回溯算法,但是没有剪枝,在42/43个case的时候超时了,以下是代码。
PS:尝试过如果当前和大于全局最小,则停止,但是由于有负数的存在,现在大的值也可以通过-9999成为最小值,剪枝失败。
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
if not triangle or not triangle[0]:
return 0
depth = len(triangle)-1
self.minSum = 9999
def helper(curSum,curdepth,j):
if curdepth == depth:
if curSum<self.minSum:
self.minSum = curSum
return
helper(curSum+triangle[curdepth + 1][j],curdepth+1,j)
helper(curSum+triangle[curdepth + 1][j+1],curdepth+1,j+1)
helper(triangle[0][0],0,0)
return self.minSum
法2)动态规划
用动态规划之前,必须想清楚,空间换时间,这里空间存储的是什么。 看了leetcodeID:吴彦祖 的解答之后,他存的是每层每个位置的最优路径和。
Greedy算法行不通的原因就是,同层最优解,在下一层可能变成非最优解,再在下一层变成最优解, 但是同一位置的最优路径不会变,所以可以存储当前位置最优路径和。
1
2 4
4 5 7
2 3 -10 -999
这样与Greedy算法区别:
Greedy: 从上层到底层遍历,每次取下一层较小值, 这样取的只是下一层的最优解
动态规划: 从上层到底层遍历,每次取上一层较小值, 这样取得是 上面所有层数得最优解, 所以遍历到最底层得时候,就是所有层数最优解,理解了!
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
if not triangle or not triangle[0]:
return 0
depth = len(triangle)
dp = [[9999 for i in range(j)] for j in range(1,depth+1)]
for i in range(depth):
for j in range(i+1):
if i == 0:
dp[i][j] = triangle[i][j]
elif j == 0:
dp[i][j] = dp[i-1][0] + triangle[i][j]
elif j == i:
dp[i][j] = dp[i-1][i-1] + triangle[i][j]
else:
if dp[i-1][j] < dp[i-1][j-1]:
dp[i][j] = dp[i-1][j] + triangle[i][j]
else:
dp[i][j] = dp[i-1][j-1] + triangle[i][j]
print(dp)
return min(dp[depth-1])
法3) 动态规划 改进空间复杂度O(1)
不设二维数组,直接在triangle上加和
来源:https://www.cnblogs.com/ChevisZhang/p/12284002.html