无去重全排列
对于某个元素作为开头的序列,如果知道了它右边的元素的全排列,就知道了以它开头的全排列
如果序列后面的元素都跟第一个元素交换位置,就知道了每个元素开头的全排列,也就知道了整个序列的全排列。
public static void permutation1(int a[],int k,int n){
if(k>=n){
for(int i=0;i<n;i++)
System.out.print(a[i]+" ");
System.out.println();
}else{
for(int i=k;i<n;i++){
swap(a,k,i);
permutation1(a,k+1,n);
swap(a,k,i);
}
}
}
这个对于任意元素都唯一的序列来说没有什么问题,但是如果有重复元素,可能产生重复的排列。比如 1,2,2
1 跟第一个 2 交换 : 2,1,2
1 跟第二个 2 交换 : 2,1,2
去重全排列
可以考虑这样来去重,每次交换 i,j 的元素的时候,必须要在 [i,j) 的区间内没有元素与 a[j] 相同。
也就是重复元素只能交换到第一个位置一次。
这样 :
1,2,2
1 跟第一个 2 交换 : 2,1,2
对于 [1,2] 序列 有 2,2,1
public static boolean hasJ(int a[],int i,int j){
for(int k=i;k<j;k++){
if(a[k]==a[j])
return true;
}
return false;
}
public static void permutation2(int a[],int k,int n){
if(k>=n){
for(int i=0;i<n;i++)
System.out.print(a[i]+" ");
System.out.println();
}else{
for(int i=k;i<n;i++){
if(!hasJ(a,k,i)){
swap(a,k,i);
permutation2(a,k+1,n);
swap(a,k,i);
}
}
}
}