[劍指offer] --27.字串的排列
阿新 • • 發佈:2018-11-15
題目描述
輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串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; } } }