
leetcode62. 不同路径
解题思路典型的递归: f(m,n) = f(m-1,n) + f(m,n-1),到达当前位置的所有路径可以来自上面一格的down,也可以是左边一格的right。
# 开辟一个dp内存,空间复杂度o(m*n) class Solution: def uniquePaths(self, m: int, n: int) -> int: dp = [[1]*n for i in range(m)] for i in range(1, m): for j in range(1, n): dp[i][j] = dp[i][j-1] + dp[i-1][j] return dp[-1][-1] # 只用一行的dp,滚动数组,节省内存,空间复杂度o(min(m,n)) class Solution: def uniquePaths(self, m: int, n: int) -> int: if m < n: m, n = n, m # 选择空间复杂度为min(m,n), dp = [1]*n for i in range(1,m): for j in range(1,n): dp[j] = dp[j]+dp[j-1] return dp[-1]扩展
如果题目不仅仅要求路径个数,还要求返回所有路径。就不能用动态规划,只能递归求解
# 时间复杂度为2^m
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
if m <= 0 or n <= 0:
return []
if m == 1 and n == 1:
return [[]]
up_path = self.uniquePaths(m-1, n)
left_path = self.uniquePaths(m, n-1)
respath = []
for path in up_path:
respath.append(path+['down'])
for path in left_path:
respath.append(path+['right'])
return respath
# 用dp保存已经得到的path,空间换时间
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dppath = [[[]]*n for _ in range(m)]
def findPath(m, n):
if m < 0 or n < 0:
return []
if m == 0 and n == 0:
return [[]]
if dppath[m][n]: return dppath[m][n]
up_path = findPath(m-1, n)
left_path = findPath(m, n-1)
respath = []
for path in up_path:
respath.append(path+['down'])
for path in left_path:
respath.append(path+['right'])
dppath[m][n] = respath
return respath
return findPath(m-1 ,n-1)
题目二: 机器人走有障碍物的方格的不同路径个数
leetcode63. 不同路径 II
# dp二维数组,空间复杂度为o(m*n)
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
row, col = len(obstacleGrid), len(obstacleGrid[0])
dp = [[0]*col for _ in range(row)]
i = 0
while i < col and obstacleGrid[0][i] == 0: # 初始化第一行,一旦有障碍物后面都为0
dp[0][i] = 1
i += 1
i = 0
while i < row and obstacleGrid[i][0] == 0: # 初始化第一列,一旦有障碍物后面都为0
dp[i][0] = 1
i += 1
for i in range(1, row):
for j in range(1, col):
if not obstacleGrid[i][j]:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[-1][-1]
# 滚动数组, 空间复杂度为o(m),没有办法o(min(m,n))了
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
row, col = len(obstacleGrid), len(obstacleGrid[0])
i = 0
dp = [0]*col
while i < col and obstacleGrid[0][i] == 0:
dp[i] = 1
i += 1
for i in range(1, row):
dp[0] = int(not obstacleGrid[i][0] and dp[0]) #初始化每行的第一列元素
for j in range(1, col):
if obstacleGrid[i][j]:
dp[j] = 0
continue
dp[j] = dp[j-1] + dp[j]
return dp[-1]
扩展
如果题目不仅仅要求路径个数,还要求返回所有路径。就不能用动态规划,同样也是递归求解。
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m, n = len(obstacleGrid), len(obstacleGrid[0])
def findPath(m, n):
if m < 0 or n < 0 or obstacleGrid[m][n]==1:
return []
if m == 0 and n == 0:
return [[]]
up_path = findPath(m-1, n)
left_path = findPath(m, n-1)
respath = []
for path in up_path:
respath.append(path+['down'])
for path in left_path:
respath.append(path+['right'])
return respath
return findPath(m-1 ,n-1)
# 用dppath 保存已经得到的path,空间换时间
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m, n = len(obstacleGrid), len(obstacleGrid[0])
dppath = [[[0]]*n for _ in range(m)] # 为了区分已遍历但因为有障碍物而无路径[]和未遍历的情况。设置[0]代表未遍历。
def findPath(m, n):
if m < 0 or n < 0:
return []
if obstacleGrid[m][n]==1:
dppath[m][n] = []
return []
if m == 0 and n == 0:
dppath[m][n] = [[]]
return [[]]
if dppath[m][n] != [0]: return dppath[m][n] #说明已经遍历过
up_path = findPath(m-1, n)
left_path = findPath(m, n-1)
respath = []
for path in up_path:
respath.append(path+['down'])
for path in left_path:
respath.append(path+['right'])
dppath[m][n] = respath
return respath
return findPath(m-1 ,n-1)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)