1. 程式人生 > >[劍指offer] --27.字串的排列

[劍指offer] --27.字串的排列

題目描述

輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。
輸入描述:
輸入一個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。

import java.util.ArrayList;
public class Solution {
    public ArrayList<String> Permutation(String str) {
       
    }
}

解題思路

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class Solution {
    public ArrayList<String> Permutation(String str) {
        List<String> resultList = new ArrayList<>();
        if(str.length() == 0)
            return (ArrayList)resultList;
        //遞迴的初始值為(str陣列,空的list,初始下標0)
        fun(str.toCharArray(),resultList,0);
        Collections.sort(resultList);
        return (ArrayList)resultList;
    }
     
    private void fun(char[] ch,List<String> list,int i){
        //這是遞迴的終止條件,就是i下標已經移到char陣列的末尾的時候,考慮新增這一組字串進入結果集中
        if(i == ch.length-1){
            //判斷一下是否重複
            if(!list.contains(new String(ch))){
                list.add(new String(ch));
                return;
            }
        }else{
            //這一段就是回溯法,這裡以"abc"為例
             
            //遞迴的思想與棧的入棧和出棧是一樣的,某一個狀態遇到return結束了之後,會回到被呼叫的地方繼續執行
             
            //1.第一次進到這裡是ch=['a','b','c'],list=[],i=0,我稱為 狀態A ,即初始狀態
            //那麼j=0,swap(ch,0,0),就是['a','b','c'],進入遞迴,自己調自己,只是i為1,交換(0,0)位置之後的狀態我稱為 狀態B 
            //i不等於2,來到這裡,j=1,執行第一個swap(ch,1,1),這個狀態我稱為 狀態C1 ,再進入fun函式,此時標記為T1,i為2,那麼這時就進入上一個if,將"abc"放進list中
            /////////////-------》此時結果集為["abc"]
             
            //2.執行完list.add之後,遇到return,回退到T1處,接下來執行第二個swap(ch,1,1),狀態C1又恢復為狀態B
            //恢復完之後,繼續執行for迴圈,此時j=2,那麼swap(ch,1,2),得到"acb",這個狀態我稱為C2,然後執行fun,此時標記為T2,發現i+1=2,所以也被新增進結果集,此時return回退到T2處往下執行
            /////////////-------》此時結果集為["abc","acb"]
            //然後執行第二個swap(ch,1,2),狀態C2迴歸狀態B,然後狀態B的for迴圈退出回到狀態A
             
            //             a|b|c(狀態A)
            //               |
            //               |swap(0,0)
            //               |
            //             a|b|c(狀態B)
            //             /  \
            //   swap(1,1)/    \swap(1,2)  (狀態C1和狀態C2)
            //           /      \
            //         a|b|c   a|c|b
             
            //3.回到狀態A之後,繼續for迴圈,j=1,即swap(ch,0,1),即"bac",這個狀態可以再次叫做狀態A,下面的步驟同上
            /////////////-------》此時結果集為["abc","acb","bac","bca"]
             
            //             a|b|c(狀態A)
            //               |
            //               |swap(0,1)
            //               |
            //             b|a|c(狀態B)
            //             /  \
            //   swap(1,1)/    \swap(1,2)  (狀態C1和狀態C2)
            //           /      \
            //         b|a|c   b|c|a
             
            //4.再繼續for迴圈,j=2,即swap(ch,0,2),即"cab",這個狀態可以再次叫做狀態A,下面的步驟同上
            /////////////-------》此時結果集為["abc","acb","bac","bca","cab","cba"]
             
            //             a|b|c(狀態A)
            //               |
            //               |swap(0,2)
            //               |
            //             c|b|a(狀態B)
            //             /  \
            //   swap(1,1)/    \swap(1,2)  (狀態C1和狀態C2)
            //           /      \
            //         c|b|a   c|a|b
             
            //5.最後退出for迴圈,結束。
             
            for(int j=i;j<ch.length;j++){
                swap(ch,i,j);
                fun(ch,list,i+1);
                swap(ch,i,j);
            }
        }
    }
     
    //交換陣列的兩個下標的元素
    private void swap(char[] str, int i, int j) {
            if (i != j) {
                char t = str[i];
                str[i] = str[j];
                str[j] = t;
            }
        }
    }