本题中重点介绍回溯法的核心代码,本文章旨在介绍清楚问题的递归回溯的代码原理,话不多说,先上代码:
def generative_permutation(nums,m):
permutation = [] #存储排好的元素
index_used = [0]*len(nums) #被使用的元素的索引
def backtrack(current_permutation):
if len(current_permutation) == m:
permutation.append(current_permutation[:]) #把当前的元素存入permutation
for i in range(len(nums)):
if index_used[i] == 0:
index_used[i] = 1
current_permutation.append(nums[i])
backtrack(current_permutation)
index_used[i] = 0
current_permutation.pop()
current_permutation = []
backtrack(current_permutation)
return permutation
n = [1,3,5]
m = 2
perm = generative_permutation(n,m)
print(perm)
现在我们思考一个问题:
回溯时的系统栈是如何运行的?例如,当permutaion=[1,3]后, pop出3后,接下来是如何找到5,使得permutaion=[1,5]的?
我来用简单的语言详细介绍一下这个过程:
其中permutation存储已经排列组合好的元素,current_permutaion存储当前正在进行排列组合的元素。index_used存储是否被使用,1为被使用,0为未被使用
当我们执行第二次backtrack,此时current_permutaion=[1,3],len(..)==m之后将current_permutaion中的元素append到permutaion之后,我们的第一组组合[1,3]就已经排列好了。接下来是如何运行的?
接下来我们将index_used[i]置为0,意思是3这个元素我们标记为了未被使用状态。紧接着我们将元素3 pop 出去,此时current_permutaion=[1],那么我们这时候按理说应该去寻找元素5,是如何做到的呢?
要知道在两次backtrack()递归时,系统栈存储了前面两次的所有状态,信息。我们这时候会回到上一层的递归状态,简单来说, 当 current_permutation
变为 [1,3]
时,系统栈中的递归状态回到了上一层。在这个上一层状态下,i
的值会在 for
循环中继续递增。所以,i
的值不会回到1,而会继续递增到2,然后在下一次递归中,会考虑 [1,5]
的组合。