全排列算法

全排列一般分为不重复和有重复

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

你可能感兴趣的:(全排列算法)