回溯采用试错的方法去解决问题,一旦发现当前步骤失败,回溯方法就返回上一个步骤,选择另一种方案继续试错。
蓝桥杯 算法提高 阮小二买彩票 Python
回溯法的特点(判断什么时候应该采用回溯算法)
例题求解:
本题中的数字有n位,如果采用常规思路,例如给出[1,2,3],那么第一个位置有3种选择,第二个位置有两种选择,第三个位置就只有一种选择了。那好,三层循环搞定!不过缺点也来了:
所以我们要写一个helper()方法,代替重复的循环
def helper(self,n, solution, rst):
if len(n) == 0:
tmp = ''.join(solution)
if tmp not in rst:
rst.append(''.join(solution))
print(''.join(solution))
return
for i in range(len(n)):
newSolution = solution + [n[i]]
newArray = n[:i] + n[i+1:]
self.helper(newArray,newSolution,rst)
代码中的参数:
helper()执行功能的过程:
(1)循环,这个地方建议等把下面的代码执行过程看完再结合思考
for i in range(len(n)):
# 把n[i]数字加入新的排序输出列表
newSolution = solution + [n[i]]
# 在排下一位置前,创建新的排序对象列表,把n[i]数字去除掉,他现在已经被选择到
newArray = n[:i] + n[i+1:]
(2)寻找下一个需要放置的数字
self.helper(newArray,newSolution,rst)
(3)递归一层一层的进行,那么终止条件是什么呢?就是n中的数字都被选出来排序了
return返回上一步骤,你会发现返回到了上一个helper()的循环函数中
仔细推演,它已经到了最后一个位置上的数字的选择,最后一个位置上只有一种选择
所以helper()会再次返回上一个,即倒数第二个位置上的数字的选择,这里的for循环会把剩余的倒数第二个位置的数字可能有的选择选择完,然后返回到倒数第三个位置,依此类推,一直到最初的第一位置的数字选择。
# 发现排序对象列表已经选完,输出当前的排序
if len(n) == 0:
tmp = ''.join(solution)
if tmp not in rst:
rst.append(''.join(solution))
print(''.join(solution))
return
完整代码:
class solution:
rst = []
solution =[]
def solvePermutation(self, n):
self.helper(n, [],[]) # 首次调用
def helper(self,n, solution, rst):
if len(n) == 0: # 发现排序对象列表已经选完,输出当前的排序
tmp = ''.join(solution)
if tmp not in rst:
rst.append(''.join(solution))
print(''.join(solution))
return # 返回上一步骤,你会发现返回到了上一个helper()的循环函数中,并且会循环下一个n[i],被加入到新的排序,新的n[i]会被去掉
for i in range(len(n)):
newSolution = solution + [n[i]] # 把n[i]加入新的排序输出列表
newArray = n[:i] + n[i+1:] # 创建新的“n”,在排下一位置前,把n[i]去除掉
self.helper(newArray,newSolution,rst) # 寻找剩余的下一位置可能的数字
if __name__ == '__main__':
n = sorted(list(input())) # 排序一遍,以符合题目要求
solution().solvePermutation(n)