字符串全排列算法學習

最近作了一道阿里的筆試題算法

1.  字符串「alibaba」有     個不一樣的排列。學習

A. 5040            B. 840               C. 14               D.420spa

用機率的辦法能夠直接求解出C73*C42*A22,C73,7是下標,3是上標,結果是420;.net

 

後來查了一下,這是一個全排列的問題,因而學習了一下全排列的算法。code

學習的博客http://blog.csdn.net/wzy_1988/article/details/8939140blog

問題

輸入一個字符串,打印出該字符串中字符的全部排列。例如輸入字符串abc,則輸出由字符a,b,c所能排列出來的全部字符串abc,acb,bac,bca,cab和cba
 
正常人的思惟是,固定第一個字符,而後依次將後面的字符串與前面的交換,那麼排列的個數就是除了第一個字符之外,其餘字符的排列個數+1。
 
也就是固定一個字符串以後,以後再將問題變小,只需求出後面子串的排列個數就能夠得出結果,固然第一時間想到的就是遞歸的算法了。
 
下面這張圖很清楚的給出了遞歸的過程:

很明顯,遞歸的出口,就是隻剩一個字符的時候,遞歸的循環過程,就是從每一個子串的第二個字符開始依次與第一個字符交換,而後繼續處理子串。
 
還有一個問題要注意,就是若是字符串中有重複的字符串
 
因爲全排列就是從第一個數字起,每一個數分別與它後面的數字交換,咱們先嚐試加個這樣的判斷——若是一個數與後面的數字相同那麼這兩個數就不交換 了。例如abb,第一個數與後面兩個數交換得bab,bba。而後abb中第二個數和第三個數相同,就不用交換了。可是對bab,第二個數和第三個數不 同,則須要交換,獲得bba。因爲這裏的bba和開始第一個數與第三個數交換的結果相同了,所以這個方法不行。

換種思惟,對abb,第一個數a與第二個數b交換獲得bab,而後考慮第一個數與第三個數交換,此時因爲第三個數等於第二個數,因此第一個數就再也不用與第三個數交換了。再考慮bab,它的第二個數與第三個數交換能夠解決bba。此時全排列生成完畢!

這樣,咱們獲得在全排列中去掉重複的規則:
去重的全排列就是從第一個數字起,每一個數分別與它後面非重複出現的數字交換。
 
因此代碼以下
 1 #include <stdio.h>
 2 
 3 static int count = 0;
 4 
 5 void swap(char* str,int a,int b)
 6 {
 7     char tmp = str[a];
 8     str[a] = str[b];
 9     str[b] = tmp;
10 }
11 
12 
13 int is_swap(char *str, int begin, int k){   //判斷從子串的第一個字符串開始,直到k-1位置,看是否有重複的字符
14     int i, flag;
15 
16     for (i = begin, flag = 1; i < k; i ++) {
17         if (str[i] == str[k]) {
18             flag = 0;
19             break;
20         }
21     }
22 
23     return flag;
24 }
25 
26 void full_permutation(char* str,int begin,int end)
27 {
28     if (begin == end)
29     {
30         count++;//此處能夠輸出字符串或者記錄字符串
31         return;
32     }else{
33         int i;
34         for (i = begin; i <= end; i++)
35         {
36             if (is_swap(str,begin,i))
37             {
38                 swap(str,begin,i);
39                 full_permutation(str,begin+1,end);
40                 swap(str,begin,i);
41             }
42         }
43     }
44 }
45 
46 int main()
47 {
48     char str[7] = {'a','l','i','b','a','b','a'};
49     full_permutation(str,0,6);
50     printf("count=%d",count);
51     return 0;
52 }

運行結果遞歸

相關文章
相關標籤/搜索