Java實(shí)現(xiàn)全排列

①假設(shè)全排列函數(shù)為f(n)=n!,那么可以立刻知道f(n+1)=(n+1)Xn!=(n+1)*f(n),因此可以利用遞歸方便地實(shí)現(xiàn)。在遞歸前所要做的事情就是把該步遞歸中的第一個(gè)元素與后面幾個(gè)元素進(jìn)行交換,并在遞歸結(jié)束后交換回來。同時(shí),當(dāng)遞歸的第一個(gè)元素移動(dòng)到數(shù)組末尾時(shí),表示完成一次排列,此時(shí)可將整個(gè)數(shù)組進(jì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{
        //打印當(dāng)前序列
        if(index>=c.length){
            for(int i=0;i<c.length;i++)
                System.out.print(c[i]+" ");
            System.out.print("\n");
            count++;
        }
        //進(jìn)行交換和遞歸
        for(int i=index;i<c.length;i++){
            if(!check(c,index,i)){     //對(duì)于重復(fù)元素,先與第一次出現(xiàn)的字符交換并求全排列,后面再出現(xiàn)的就不進(jìn)行交換和求全排列的過程
                swap(c,index,i);
                perm(c,index+1);
                swap(c,index,i);
            }
        }
    }
    //數(shù)組里兩個(gè)值交換
    private static void swap(char[] c,int index1,int index2)throws Exception{
        char t=c[index1];
        c[index1]=c[index2];
        c[index2]=t;
    }
    //去重函數(shù)
    private static boolean check(char[] c,int index1,int index2){
        while(index1<index2){
            if(c[index1]==c[index2])
                return true;
            index1++;
        }
        return false;
    }
}

????????其中去重函數(shù)并不是必要的。
②第二種方式不通過遞歸而是迭代實(shí)現(xiàn)。迭代方法借助了字典序。字典序顧名思義就是在編排字典時(shí)采用的排序方式。比如單詞monster和monitor,它們前三個(gè)字母相同,第四個(gè)字母s比i大,因此monster會(huì)排在monitor的后面。
????????使用字典序的關(guān)鍵是找到當(dāng)前序列所緊挨著的下一個(gè)序列。假設(shè)有序列a,一般思路是從a的末尾開始比較a[index-1]和a[index],若a[index-1]<a[index],記flag=index-1,否則繼續(xù)往前搜索。找到flag后,查找flag后面的元素,記后面所有大于flag的元素中最小的那個(gè)元素的索引為min,交換a[flag]和a[min],然后對(duì)a[flag]后的元素由小到大排序,即得到所需的下一個(gè)序列。若在遍歷時(shí)找不到flag,則序列自身已是從大到小排列,不存在下一個(gè)字典序列,迭代結(jié)束。
????????因此,可先將原序列從小到大排序,獲取最小序列,然后一直迭代直到找不到下一個(gè)序列為止。代碼如下。

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);
    }
    
    //獲取下一個(gè)字典序列
    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;
    }
    //對(duì)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);
        }
    }
    //打印數(shù)組
    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]+" ");
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容