1. 程式人生 > >演算法--字串的排列

演算法--字串的排列

       今天做了一個演算法題目,當時沒做出來,參考了一下網上的答案,雖然說弄明白了怎麼回事,但是感覺下次遇到了可能還是會做不出來,所以先把解題思路記下來,以後時常回顧一下。

題目描述:

   輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串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 = new
ArrayList<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 }

參考連線:

https://blog.csdn.net/zjxxyz123/article/details/79709240