字符串全排列算法

問題:輸入一個字符串,打印出該字符串中字符的所有排列。例如輸入字符串a(chǎn)bc,則輸出由字符a,b,c所能排列出來的所有字符串a(chǎn)bc,acb,bac,bca,cab和cba。

? ? ? 正常人的思維是,固定第一個字符,然后依次將后面的字符串與前面的交換,那么排列的個數(shù)就是除了第一個字符以外,其他字符的排列個數(shù)+1。也就是固定一個字符串之后,之后再將問題變小,只需求出后面子串的排列個數(shù)就可以得出結(jié)果,當(dāng)然第一時間想到的就是遞歸的算法了。下面這張圖很清楚的給出了遞歸的過程:


? ? 很明顯,遞歸的出口,就是只剩一個字符的時候,遞歸的循環(huán)過程,就是從每個子串的第二個字符開始依次與第一個字符交換,然后繼續(xù)處理子串。

代碼:

importjava.util.List;

import java.util.Collections;

import java.util.ArrayList;

public class Solution {

????public static void main(String[] args) {

????????Solution p = new Solution();

????????System.out.println(p.Permutation("abc").toString());

????}

? ?public ArrayList Permutation(String str) {

????????List res = new ArrayList<>();

????????if(str != null&& str.length() > 0) {

????????????PermutationHelper(str.toCharArray(), 0, res);

????????????Collections.sort(res);

????????}

????????return(ArrayList)res;

????}

????public void PermutationHelper(char[] cs, int i, List list) {

????????if(i == cs.length - 1) {

????????????String val = String.valueOf(cs);

????????????if(!list.contains(val))

????????????????list.add(val);

????????} else{

????????????for(int j = i; j < cs.length; j++) {

????????????????swap(cs, i, j);

????????????????PermutationHelper(cs, i+1, list);

????????????????swap(cs, i, j);

????????????}

????????}

????}

????publicvoidswap(char[] cs, inti, intj) {

????????chartemp = cs[i];

????????cs[i] = cs[j];

????????cs[j] = temp;

????}

}

? ? 此處使得排列不重復(fù)使用的方法是判斷:???if(!list.contains(val))。

? ? 還有一個問題要注意,就是如果字符串中有重復(fù)的字符串。由于全排列就是從第一個數(shù)字起,每個數(shù)分別與它后面的數(shù)字交換,我們先嘗試加個這樣的判斷——如果一個數(shù)與后面的數(shù)字相同那么這兩個數(shù)就不交換 了。例如abb,第一個數(shù)與后面兩個數(shù)交換得bab,bba。然后abb中第二個數(shù)和第三個數(shù)相同,就不用交換了。但是對bab,第二個數(shù)和第三個數(shù)不 同,則需要交換,得到bba。由于這里的bba和開始第一個數(shù)與第三個數(shù)交換的結(jié)果相同了,因此這個方法不行。

換種思維,對abb,第一個數(shù)a與第二個數(shù)b交換得到bab,然后考慮第一個數(shù)與第三個數(shù)交換,此時由于第三個數(shù)等于第二個數(shù),所以第一個數(shù)就不再用與第三個數(shù)交換了。再考慮bab,它的第二個數(shù)與第三個數(shù)交換可以解決bba。此時全排列生成完畢!

這樣,我們得到在全排列中去掉重復(fù)的規(guī)則:

去重的全排列就是從第一個數(shù)字起,每個數(shù)分別與它后面非重復(fù)出現(xiàn)的數(shù)字交換。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,652評論 18 399
  • 今天面試一家公司,因為簡歷上寫了ACM經(jīng)歷,被問到了PHP字符串全排列算法,當(dāng)時時間有限只給了思路,回家后把它實現(xiàn)...
    靈魂放逐閱讀 1,700評論 0 0
  • 前言 最先接觸編程的知識是在大學(xué)里面,大學(xué)里面學(xué)了一些基礎(chǔ)的知識,c語言,java語言,單片機的匯編語言等;大學(xué)畢...
    oceanfive閱讀 3,382評論 0 7
  • 冷暖無常早已有, 名為春天又象秋。 形如人生多變化, 有時喜來有時愁。 生活如同大海水, 也可沉來也可浮。 事出有...
    艷菊疏影閱讀 340評論 0 0
  • 自21世紀初以來,神經(jīng)學(xué)家就已經(jīng)對大腦中的兩種思維網(wǎng)絡(luò)模式的互相切換取得了研究上的長足進步,即注意力...
    姓王名錕閱讀 1,273評論 0 1

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