Java實現全排列

①假設全排列函數為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]+" ");
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容