字典序算法


一個全排列可看做一個字符串,字符串可有前綴、后綴。

生成給定全排列的下一個排列.所謂一個的下一個就是這一個與下一個之間沒有其他的。這就要求這一個與下一個有盡可能長的共同前綴,也即變化限制在盡可能短的后綴上。

[例]839647521是1--9的排列。1—9的排列最前面的是123456789,最后面的987654321,從右向左掃描若都是增的,就到了987654321,也就沒有下一個了。否則找出第一次出現下降的位置。

就是找變化最小的。

例子:

【例】 如何得到346987521的下一個 1,從尾部往前找第一個P(i-1) < P(i)的位置 3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1 最終找到6是第一個變小的數字,記錄下6的位置i-1
    2,從i位置往后找到最后一個大於6的數 3 4 6 -> 9 -> 8 -> 7 5 2 1 最終找到7的位置,記錄位置為m 3,交換位置i-1和m的值 3 4 7 9 8 6 5 2 1
    4,倒序i位置后的所有數據 3 4 7 1 2 5 6 8 9 則347125689為346987521的下一個排列

代碼如下:

private static void PermutationList() { int fromIndex, endIndex, changeIndex; Sort(0, length - 1); do { // 輸出一種全排列
 Output(); fromIndex = endIndex = length - 1; // 向前查找第一個變小的元素
                while (fromIndex > 0 && words[fromIndex] < words[fromIndex - 1]) --fromIndex;//有重復字符的情況改為words[fromIndex] <= words[fromIndex - 1]
                changeIndex = fromIndex; if (fromIndex == 0) break; // 向后查找最后一個大於words[fromIndex-1]的元素
                while (changeIndex + 1 < length && words[changeIndex + 1] > words[fromIndex - 1]) ++changeIndex; Swap(fromIndex - 1, changeIndex);   // 交換兩個值
                InvertArray(fromIndex, endIndex);   // 對后面的所有值進行反向處理
            } while (true); }

 

遞歸算法:

 

固定第一個字符,然后依次將后面的字符串與前面的交換,那么排列的個數就是除了第一個字符以外,其他字符的排列個數+1。也就是固定一個字符串之后,之后再將問題變小,只需求出后面子串的排列個數就可以得出結果。
 
 

遞歸的出口,就是只剩一個字符的時候,遞歸的循環過程,就是從每個子串的第二個字符開始依次與第一個字符交換,然后繼續處理子串。

代碼如下:

public static void main (String[] args){
        Solution p = new Solution();
        System.out.println(p.Permutation("abc").toString());
    }
    public ArrayList<String> Permutation(String str) {
        List <String> res = new ArrayList();
        if (str != null&& str.length() > 0 ){
            per(str.toCharArray(),0,res);
            Collections.sort(res);
        }
        return (ArrayList)res;
    }
    public void per(char[] ch, int i,List<String> res){
        if ( i == ch.length-1){
            String val =String.valueOf(ch);
            if (!res.contains(val))//判斷是否重復,重復則不加入
                res.add(val);
        }
        else{for (int j = i ;j<ch.length;j++){
        swap(ch,i,j);
        per(ch,i+1,res);
        swap(ch,i,j);
    }}}
 
     public void swap(char[] cs, int i, int j) {
        char temp = cs[i];
        cs[i] = cs[j];
        cs[j] = temp;
    }

 

參考自:https://www.cnblogs.com/cxjchen/p/3932949.html

    https://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM