全排列
全排列就是将给定序列的所有排列方式找出。
递归解法
有重复
如下这种方式使用递归,将整组数中的所有的数分别与第一个数交换swap(start,i);,这样就总是在处理后n-1个全排列。
1 | function perm(list,start,end){ |
去重复
那么在这种递归的方法中,如何去掉重复的全排列呢。
先举个例子:1,2,2
在这个数组中将第一个数与第二个数交换得到2,1,2,将第一个与第三个交换得到2,2,1
然后将2,1,2中的第二个与第三个交换2,2,1,额,,,发生了重复,咱们需要转换思路了。
重新梳理。将第一个数与第二个数交换得到2,1,2,然后发现第二个数与第三个数相同,于是第一个数不再与第三个数交换。
再考虑2,1,2,将第二个数与第三个数交换得到2,2,1.此时全排列完成。
这样我们也得到了在全排列中去掉重复项的规则:去重的全排列就是从第一个数字起,每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j]中没有与第j个数相等的数。
新添加了一个isSwap函数:
1 | function perm(list,start,end){ |
字典排序法
全排列的另外一种方法是字典排序法。
字典排序法,就是在数组中,从后往前找,找到第一个非递增数比如1,2,4,3中2就是从前往后第一个非递增数。
然后再次从后往前找,找到第一个大于2的数,在这里就是3,交换2和3,数组变成1,3,4,2。
最后再逆置3后面的数即1,3,2,4
1 | function main(list){ |