演算法--字串的排列
阿新 • • 發佈:2018-12-30
今天做了一個演算法題目,當時沒做出來,參考了一下網上的答案,雖然說弄明白了怎麼回事,但是感覺下次遇到了可能還是會做不出來,所以先把解題思路記下來,以後時常回顧一下。
題目描述:
輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。輸入描述:
輸入一個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。
解題思路:
這是一道經典的DFS題目,利用回溯的思想找到一個字元陣列的全排列,並完成去重與字典序排序操作。
大致思想便是,先確定第i個字元(從i到最後完成遍歷列舉),然後對i+1-N-1個字元遞迴使用全排列(縮小範圍),這便是dfs。
但因為DFS過程必須向後序遞迴過程傳遞剩下的字元,那麼如何傳遞呢?
每一次確定字元後,將剩餘字元裝入一個容器中,傳遞下去。但這樣會增加許多拷貝遍歷操作,極其麻煩。
另一種方法,便是將確定的字元與當前第 i個字元相交換,然後i+1-N-1依然是剩下的字元。
但是要注意,這樣做改變了字元陣列,必須進行完一次dfs過程後,將陣列復原,便於確定i位置其他元素時,不會受到影響。
如何完成去重?
從圖中可以發現,只要每一層確定的字元不一樣,那麼便不會出現重複元素,換句話說,只要每一次遞迴列舉確定i元素時,不出現重複的即可,這可用set實現,這比上述方法,提前去重,避免了後序很多無謂的遞迴。
程式碼實現:
1 import java.util.*; 2 public class Solution { 3 public ArrayList<String> Permutation(String str) { 4 ArrayList<String> result = newArrayList<String>(); 5 if (str == null || str.length() == 0) { 6 return result; 7 } 8 char[] chArray = str.toCharArray(); 9 findPerutation(result, chArray, 0); 10 Collections.sort(result); 11 return result; 12 } 13 private void findPerutation(ArrayList<String> result, char[] chArray, int i) { 14 if (i == chArray.length) { 15 result.add(new String(chArray)); 16 return; 17 } 18 HashSet<Character> set = new HashSet<Character>(); 19 for (int j = i; j < chArray.length; j++) { 20 if (set.contains(chArray[j])) { 21 continue; 22 } 23 set.add(chArray[j]); 24 // 交換 25 swap(i, j, chArray); 26 // 遞迴 27 findPerutation(result, chArray, i + 1); 28 // 還原順序 29 swap(i, j, chArray); 30 } 31 } 32 private void swap(int i, int j, char[] chArray) { 33 if (i == j) { 34 return; 35 } 36 char temp = chArray[i]; 37 chArray[i] = chArray[j]; 38 chArray[j] = temp; 39 } 40 }
參考連線: