①假設全排列函數為f(n)=n!,那么可以立刻知道f(n+1)=(n+1)Xn!=(n+1)*f(n),因此可以利用遞歸方便地實現。在遞歸前所要做的事情就是把該步遞歸中的第一個元素與后面幾個元素進行交換,并在遞歸結束后交換回來。同時,當遞歸的第一個元素移動到數組末尾時,表示完成一次排列,此時可將整個數組進行輸出。代碼如下:
public class exam {
static int count;
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
count=0;
String str="aabb";
char[] cs=str.toCharArray();
perm(cs,0);
System.out.print(count);
System.exit(0);
}
//全排列的遞歸算法
private static void perm(char[] c,int index)throws Exception{
//打印當前序列
if(index>=c.length){
for(int i=0;i<c.length;i++)
System.out.print(c[i]+" ");
System.out.print("\n");
count++;
}
//進行交換和遞歸
for(int i=index;i<c.length;i++){
if(!check(c,index,i)){ //對于重復元素,先與第一次出現的字符交換并求全排列,后面再出現的就不進行交換和求全排列的過程
swap(c,index,i);
perm(c,index+1);
swap(c,index,i);
}
}
}
//數組里兩個值交換
private static void swap(char[] c,int index1,int index2)throws Exception{
char t=c[index1];
c[index1]=c[index2];
c[index2]=t;
}
//去重函數
private static boolean check(char[] c,int index1,int index2){
while(index1<index2){
if(c[index1]==c[index2])
return true;
index1++;
}
return false;
}
}
????????其中去重函數并不是必要的。
②第二種方式不通過遞歸而是迭代實現。迭代方法借助了字典序。字典序顧名思義就是在編排字典時采用的排序方式。比如單詞monster和monitor,它們前三個字母相同,第四個字母s比i大,因此monster會排在monitor的后面。
????????使用字典序的關鍵是找到當前序列所緊挨著的下一個序列。假設有序列a,一般思路是從a的末尾開始比較a[index-1]和a[index],若a[index-1]<a[index],記flag=index-1,否則繼續往前搜索。找到flag后,查找flag后面的元素,記后面所有大于flag的元素中最小的那個元素的索引為min,交換a[flag]和a[min],然后對a[flag]后的元素由小到大排序,即得到所需的下一個序列。若在遍歷時找不到flag,則序列自身已是從大到小排列,不存在下一個字典序列,迭代結束。
????????因此,可先將原序列從小到大排序,獲取最小序列,然后一直迭代直到找不到下一個序列為止。代碼如下。
public class PermInteration {
public static void main(String[] args) {
int count=0;
String str="hbbb";
char[] c=str.toCharArray();
sort(c,0); //先排序
print(c);
count++;
while(getNextPerm(c)){
count++;
}
System.out.println(count);
System.exit(0);
}
//獲取下一個字典序列
private static boolean getNextPerm(char[] c){
int end=c.length-1;
int flag=0;
int min=0;
int index=end;
while(index>0&&c[index]<=c[index-1]){
index--;
}
if(index==0)
return false;
flag=index-1;
min=index;
for(int i=index;i<=end;i++){
if(c[i]>c[flag]&&c[i]<c[min])
min=i;
}
swap(c,flag,min);
sort(c,index);
print(c);
return true;
}
//交換
private static void swap(char[] c,int index1,int index2){
char t=c[index1];
c[index1]=c[index2];
c[index2]=t;
}
//對index及后面的元素排序
private static void sort(char[]c,int index){
int min;
for(int i=index;i<c.length-1;i++){
min=i;
for(int j=i;j<c.length;j++){
if(c[j]<c[min])
min=j;
}
swap(c,i,min);
}
}
//打印數組
private static void print(char[] c){
for(int i=0;i<c.length;i++){
if(i==c.length-1)
System.out.print(c[i]+"\n");
else
System.out.print(c[i]+" ");
}
}
}