求最小路径和
方法1 DP法
递推方程很容易写
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
class Solution(object):
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
dp = [[0] * len(grid[0]) for i in range(len(grid))]
for i in range(len(dp)):
for j in range(len(dp[0])):
if i == 0 and j == 0: dp[i][j] = grid[i][j]
elif i == 0: dp[i][j] = dp[i][j-1] + grid[i][j]
elif j == 0: dp[i][j] = dp[i-1][j] + grid[i][j]
else: dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
return dp[-1][-1]
我们完全可以不用判断边界,如果边界越界时取的值为无限大,那么越界的元素则不会产生影响,我们通过让初始值为无限大即可,代码可以变得更简洁。注意第一个元素要单独赋值。
class Solution(object):
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
dp = [[float("inf")] * len(grid[0]) for i in range(len(grid))]
for i in range(len(dp)):
for j in range(len(dp[0])):
if i + j == 0:
dp[i][j] = grid[i][j]
continue
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
return dp[-1][-1]
改进的DP O(n) space
我们发现DP中的二维数组,每次更新的时候实际只用到了当前元素左边和上边的元素,我们用个一维数组space即可,当遍历到第[i,j]元素时,space[i-1]已经被更新过了,相当于dp[i][j-1], 而space[i]更新前代表dp[i-1][j]。
按行更新space,space[0]需要差别对待,每次都加上row的第一个元素
class Solution(object):
def minPathSum(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
space = [float("inf") for i in range(len(grid[0]))]
space[0] = 0
for row in grid:
for i in range(len(row)):
if i == 0:
space[i] += row[i]
else:
space[i] = min(space[i-1], space[i]) + row[i]
return space[-1]
方法2 递归法
用dict存储值,当查询不到时进行递归求key的value,并更新dict
class Solution(object):
def minPathSum(self, grid):
self.dict = {}
return self.helper(len(grid)-1, len(grid[0])-1 ,grid)
def helper(self, x, y, grid):
if x == 0 and y == 0:
return grid[0][0]
else:
key = str(x) + "-" + str(y)
if key not in self.dict:
if x == 0:
self.dict[key] = self.helper(x, y-1, grid) + grid[x][y]
elif y == 0:
self.dict[key] = self.helper(x-1, y, grid) + grid[x][y]
else:
self.dict[key] = min(self.helper(x-1, y, grid), self.helper(x, y-1, grid)) + grid[x][y]
return self.dict[key]