全排列一般分为不重复和有重复
1.无重复
无重复的话一般都是n!种排列
1.1递归回溯法
时间复杂度:O(n * n!)
主体思想就是换位:每一个位置有和其他位置换位和不换位两种情况,假设限制有三个字母[a,b,c]
每次将首位字母与后面的字母依次换位置,每次结束后将后一位的看作首字母。(但是为了不影响后面的结果,每次都要回溯,换了位置之后还要把位置换回来)
f([a])=[a]
f([a,b]) = [a,f(b)],[b,f(a)]
f([a,b,c]) = [a,f([b,c])],[b,f([a,c])],[c,f([a,b])]
[a,f([b,c])] = [a,b,f(c)],[a,b,f(b)]
[b,f([a,c])] = [b,a,f(c)],[b,c,f(a)]
[c,f([a,b])] = [c,a,f(b)],[c,b,f(a)]
最后的结果就是[a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]
共6种情况
listpath = []
start = 0
ss = ['1','2','3']
def permuation(start,ss,listpath):
if start==len(ss):
listpath.append(''.join(ss))
else:
for i in range(start,len(ss)):
ss[start],ss[i]=ss[i],ss[start]
#start+1而不是i+1,因为这里每一次都是在start内循环完毕之后再交换缩小
# i大部分时候比start大,会直接导致有些位置并没有交换
permuation(start+1,ss,listpath)
ss[start],ss[i]=ss[i],ss[start]
permuation(start,ss,listpath)
print(listpath)
#out:['123', '132', '213', '231', '321', '312']
1.2
2.有重复
有重复的话就每次考虑交换位置的两个元素是否相等,相等的话就没必要换了,重复了
listpath = []
ss = ['1','1','3']
start = 0
def permuation(start,ss,listpath):
if start==len(ss):
print(ss)
listpath.append(''.join(ss))
print(listpath)
else:
for i in range(start,len(ss)):
if i==start or ss[start]!=ss[i]:
ss[start],ss[i]=ss[i],ss[start]
permuation(start+1,ss,listpath)
ss[start],ss[i]=ss[i],ss[start]
permuation(start,ss,listpath)
print(listpath)
#out:['113', '131', '311']
参考-csdn
参考-nowcoder