①假设全排列函数为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]+" ");
}
}
}