[劍指offer]字串的排列
阿新 • • 發佈:2018-12-16
思路:
使用遞迴逐個交換,注意交換完後開始新的交換時需要恢復交換之前的狀態,即回溯
A和A交換,A和B交換,A和C交換,之後再分別進行各自的不同交換,在交換記錄之後回到上一次交換時的狀態。
實現:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Solution {
public ArrayList<String> Permutation(String str) {
List<String> list = new ArrayList<String>();
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 <String> list){
if(i == cs.length -1){
String val = String.valueOf(cs);
if(!list.contains(val))
list.add(val);
}
else{
//遞迴的思想與棧的入棧和出棧是一樣的,某一個狀態遇到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 < cs.length ; j++){
swap(cs,i,j);
PermutationHelper(cs,i+1,list);
swap(cs,i,j);
}
}
}
public void swap(char []cs, int i, int j){
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
}