【发布时间】:2021-04-18 09:24:21
【问题描述】:
最近在我的作业中,我被分配解决以下问题:
给定一个由 0 和 1 组成的 nxn 阶矩阵,找出从 [0,0] 到 [n-1,n-1] 仅经过零(它们不一定不相交)的路径数只能向下或向右走,从不向上或向左。返回一个同阶矩阵,其中 [i,j] 项是原始矩阵中经过 [i,j] 的路径数,解必须是递归的。
我在 python 中的解决方案:
def find_zero_paths(M):
n,m = len(M),len(M[0])
dict = {}
for i in range(n):
for j in range(m):
M_top,M_bot = blocks(M,i,j)
X,Y = find_num_paths(M_top),find_num_paths(M_bot)
dict[(i,j)] = X*Y
L = [[dict[(i,j)] for j in range(m)] for i in range(n)]
return L[0][0],L
def blocks(M,k,l):
n,m = len(M),len(M[0])
assert k<n and l<m
M_top = [[M[i][j] for i in range(k+1)] for j in range(l+1)]
M_bot = [[M[i][j] for i in range(k,n)] for j in range(l,m)]
return [M_top,M_bot]
def find_num_paths(M):
dict = {(1, 1): 1}
X = find_num_mem(M, dict)
return X
def find_num_mem(M,dict):
n, m = len(M), len(M[0])
if M[n-1][m-1] != 0:
return 0
elif (n,m) in dict:
return dict[(n,m)]
elif n == 1 and m > 1:
new_M = [M[0][:m-1]]
X = find_num_mem(new_M,dict)
dict[(n,m-1)] = X
return X
elif m == 1 and n>1:
new_M = M[:n-1]
X = find_num_mem(new_M, dict)
dict[(n-1,m)] = X
return X
new_M1 = M[:n-1]
new_M2 = [M[i][:m-1] for i in range(n)]
X,Y = find_num_mem(new_M1, dict),find_num_mem(new_M2, dict)
dict[(n-1,m)],dict[(n,m-1)] = X,Y
return X+Y
我的代码基于这样的想法,即在原始矩阵中通过 [i,j] 的路径数等于从 [0,0] 到 [i,j] 的路径数的乘积,并且从 [i,j] 到 [n-1,n-1] 的路径数。另一个想法是从 [0,0] 到 [i,j] 的路径数是从 [0,0] 到 [i-1,j] 和从 [0,0] 到[i,j-1]。因此我决定使用一个字典,其键是 [[M[i][j] for j in range(k)] for i in range(l)] 或 [[M[i][j] for j in range(k+1,n)] for i in range(l+1,n)] for some 0
现在,我的导师说这段代码是指数型的(对于 find_zero_paths),但我不同意。 递归树(对于 find_num_paths)的大小受上述形式的子矩阵数量的限制,即 O(n^2)。此外,每次我们在字典中添加一个新矩阵时,我们都会在多项式时间内完成(仅切片列表),所以......总复杂度是多项式(poly*poly = poly)。此外,函数“blocks”在多项式时间内运行,因此“find_zero_paths”在多项式时间内运行(2 个多项式大小列表乘以在多项式时间内运行的函数),因此所有代码都在多项式时间内运行。
我的问题:代码多项式和我的 O(n^6) 界限是错误的还是指数级的,我错过了什么?
【问题讨论】:
-
如果有一个零循环,路径的数量将是无限的。请问这有什么办法吗? (例如,通过指定没有循环或仅寻找最短路径)此外,听说您需要使用递归有点痛苦。这有什么原因吗?
-
我忘了说你只能往下走或往右走,不能往回走或往上走,因此没有循环,修复它。另外,递归的原因只是因为作业的主题是递归。
标签: python algorithm time-complexity path-finding