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

[劍指offer]字串的排列

在這裡插入圖片描述
思路:
使用遞迴逐個交換,注意交換完後開始新的交換時需要恢復交換之前的狀態,即回溯
在這裡插入圖片描述
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; } }