全排列
1.解法
排列问题也是回溯问题的一种。
所以我们可以先画出树图:
排列问题和组合问题的区别在于,剩余集合中元素相同时,组合只取其中一种,不考虑顺序问题,而排列则要考虑到顺序问题。例如剩余集合[2,3]时,组合[2,3]、[3,2]是同样的,而排列[2,3]、[3,2]是不同的。
所以由图可知,我们每从(剩余)集合中选择一个数,就要再遍历一次集合,从里面选择没选过的数,所以我们可以用一个数组used来记录哪些数值没选择过,这样一来就可以写下如下代码:
for i in range(len(nums)): # 遍历集合
if used[i] == 1:
continue
path.append(nums[i]) # path用来存储当前得到的排列
used[i] = 1
递归
used[i] = 0
path.pop()
现在按照回溯三部曲来写代码:
-
写出函数头和一些辅助变量:
result = [] path = [] used = [0] * len(nums) def backtracking(nums,used)
-
写出递归出口:
由图可知,递归出口就是当取到叶子节点的时候,而叶子节点的特征就是len(path)==len(nums),所以可以这样写递归出口:
if len(path)==len(nums): path1 = path.copy() result.append(path1) return
-
写出函数逻辑:
上面已经分析过了递归逻辑了,这里具体写一下:
for i in range(len(nums)): # 遍历集合 if used[i] == 1: continue path.append(nums[i]) # path用来存储当前得到的排列 used[i] = 1 backtracking(nums,used) used[i] = 0 path.pop()
完整代码:
def permute(nums):
result = []
path = []
used = [0]*len(nums)
def backtracking(nums,used):
if len(path)==len(nums):
path1 = path.copy()
result.append(path1)
return
for i in range(len(nums)):
if used[i] == 1:
continue
used[i] = 1
path.append(nums[i])
backtracking(nums,used)
path.pop()
used[i] = 0
backtracking(nums,used)
return result
2.总结
排列问题:需要使用used数组来记录