版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/82797218
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
解题思路
一个最简单的思路就是将所有数往下加,但是在层数>=3
的时候会出现这样的问题。
2
5 6
11 (10,11) 13
那么我们这个时候就取最小值10
,然后再往下加。
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
if not triangle:
return 0
return self._minimumTotal(0, 0, triangle)
def _minimumTotal(self, row, col, triangle):
if row + 1 == len(triangle):
return triangle[row][col]
return triangle[row][col] + min(self._minimumTotal(row + 1, col, triangle), self._minimumTotal(row + 1, col + 1, triangle))
但是这样做存在着大量的重复运算(在哪呢?)。我们可以通过记忆化搜索的方式来优化上面的问题。
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
if not triangle:
return 0
mem = [[None for i in range(len(triangle))] for j in range(len(triangle))]
print(mem)
return self._minimumTotal(0, 0, triangle, mem)
def _minimumTotal(self, row, col, triangle, mem):
if row + 1 == len(triangle):
return triangle[row][col]
if mem[row][col]:
return mem[row][col]
mem[row][col] = triangle[row][col] + \
min(self._minimumTotal(row + 1, col, triangle, mem), \
self._minimumTotal(row + 1, col + 1, triangle, mem))
return mem[row][col]
显然这种写法很麻烦,我们追求的是优雅的编程( ̄▽ ̄)"。我们不妨将金字塔倒过来
[
[4,1,8,3],
[6,5,7],
[3,4],
[2]
]
我们只要再相邻的元素中选出最下的值,然后往对应的下一层加即可。例如[4,1,8,3]
,4
和1
比,1
小,所以我们将1
加到下一层的6
。接着,考虑1
和8
,我们将1
加到下一层的5
,接着考虑8
和3
,我们将3
加到7
,以此类推下去。
基于这个思想我们可以写出这样的代码
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
if not triangle:
return 0
for row in range(len(triangle) - 1, 0, -1):
for col, _ in enumerate(triangle[row - 1]):
triangle[row - 1][col] += min(triangle[row][col] ,triangle[row][col + 1])
return triangle[0][0]
当然这里的for col, _ in enumerate(triangle[row - 1]):
写成for col in range(row):
更加简洁。当然我们可以将上面的代码继续简化
import functools
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
return functools.reduce(lambda a,b:[f+min(d,e)for d,e,f in zip(a,a[1:],b)],triangle[::-1])[0]
Just one line!!!但是这种写法一点也不优雅。
reference:
https://leetcode.com/problems/triangle/discuss/38827/One-liner-in-Python
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!