为什么这两个回溯算法有相同的输出?
Why this two backtracking algorithm have same outputs?
我已经实现了两个回溯算法来解决 Codewars (https://www.codewars.com/kata/5a6b24d4e626c59d5b000066) 上的这个挑战。我的问题是我理解为什么第一个实现有效但不理解第二个实现的原因。我认为我的问题出在最后一行带有哈希符号的 return 语句中。我不明白为什么当回溯终止时,因为找到了解决方案,第二个实现 return 是正确的解决方案而不是空列表。是因为当解决方案传递给函数的上一次调用时,他在上一次调用中的值(少了一个元素)被完整的解决方案覆盖了吗?
第一个:
def square_sums_row(n):
a , sol = [ x for x in range(1,n+1)] , []
def recurse(a,sol):
if a == [] :
return sol
for i,x in enumerate(a) :
if is_valid(x,sol) :
sol.append(x)
iterate = recurse(a[:i]+a[i+1:],sol) ###########
if iterate : ###########
return iterate #########
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(a,sol)
第二个:
def square_sums_row(n):
s , sol = [ x for x in range(1,n+1)] , []
def recurse(s,sol):
if s == [] :
return sol
for i,x in enumerate(s) :
if is_valid(x,sol) :
sol.append(x)
if recurse(s[:i]+s[i+1:],sol) : ###########
return sol ##############
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(s,sol)
之所以有效,是因为它们 return 相同,两个解决方案 return sol
。只是第二个 return 直接是变量 sol
,而第一个 return 是函数的输出(与作为参数传递的变量 sol
相同).
为了扩展另一个答案,只有一个列表对象 sol
被传递和返回。它永远不会被复制。这是强调这一点的另一种解决方案。这里 sol
不是任何地方的参数,它只是从闭包中获取,内部函数只返回布尔值。
def square_sums_row(n):
sol = []
def recurse(s):
if s == []:
return True
for i, x in enumerate(s):
if is_valid(x):
sol.append(x)
iterate = recurse(s[:i] + s[i + 1:]) ###########
if iterate: ###########
return True
sol.pop(-1)
return False
def is_valid(x):
if len(sol) == 0:
return True
if ((sol[-1] + x) ** 0.5) % 1 == 0:
return True
return False
if recurse([x for x in range(1, n + 1)]):
return sol
else:
return False
我已经实现了两个回溯算法来解决 Codewars (https://www.codewars.com/kata/5a6b24d4e626c59d5b000066) 上的这个挑战。我的问题是我理解为什么第一个实现有效但不理解第二个实现的原因。我认为我的问题出在最后一行带有哈希符号的 return 语句中。我不明白为什么当回溯终止时,因为找到了解决方案,第二个实现 return 是正确的解决方案而不是空列表。是因为当解决方案传递给函数的上一次调用时,他在上一次调用中的值(少了一个元素)被完整的解决方案覆盖了吗?
第一个:
def square_sums_row(n):
a , sol = [ x for x in range(1,n+1)] , []
def recurse(a,sol):
if a == [] :
return sol
for i,x in enumerate(a) :
if is_valid(x,sol) :
sol.append(x)
iterate = recurse(a[:i]+a[i+1:],sol) ###########
if iterate : ###########
return iterate #########
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(a,sol)
第二个:
def square_sums_row(n):
s , sol = [ x for x in range(1,n+1)] , []
def recurse(s,sol):
if s == [] :
return sol
for i,x in enumerate(s) :
if is_valid(x,sol) :
sol.append(x)
if recurse(s[:i]+s[i+1:],sol) : ###########
return sol ##############
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(s,sol)
之所以有效,是因为它们 return 相同,两个解决方案 return sol
。只是第二个 return 直接是变量 sol
,而第一个 return 是函数的输出(与作为参数传递的变量 sol
相同).
为了扩展另一个答案,只有一个列表对象 sol
被传递和返回。它永远不会被复制。这是强调这一点的另一种解决方案。这里 sol
不是任何地方的参数,它只是从闭包中获取,内部函数只返回布尔值。
def square_sums_row(n):
sol = []
def recurse(s):
if s == []:
return True
for i, x in enumerate(s):
if is_valid(x):
sol.append(x)
iterate = recurse(s[:i] + s[i + 1:]) ###########
if iterate: ###########
return True
sol.pop(-1)
return False
def is_valid(x):
if len(sol) == 0:
return True
if ((sol[-1] + x) ** 0.5) % 1 == 0:
return True
return False
if recurse([x for x in range(1, n + 1)]):
return sol
else:
return False