字串的排列

2021-09-08 11:18:48 字數 3475 閱讀 3928

輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。 

輸入描述:

輸入乙個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。
1

class

solution

11private:12

void stringpermutation(string &str,int begin,int end,vector&res)23}

24}25bool issame(string str,int begin,int

end)

30return

false;31

}32 };

**

問題1 :輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a、b、c所能排列出來的所有字串abc、acb、bac、bca、cab和cba。

思路:這是個遞迴求解的問題。遞迴演算法有四個特性:(1)必須有可達到的終止條件,否則程式將陷入死迴圈;(2)子問題在規模上比原問題小;(3)子問題可通過再次遞迴呼叫求解;(4)子問題的解應能組合成整個問題的解。

對於字串的排列問題。如果能生成n - 1個元素的全排列,就能生成n個元素的全排列。對於只有1個元素的集合,可以直接生成全排列。全排列的遞迴終止條件很明確,只有1個元素時。下面這個圖很清楚的給出了遞迴的過程。

1

//函式功能 : 求乙個字串某個區間內字元的全排列2//

函式引數 : pstr為字串,begin和end表示區間3//

返回值 : 無

4void permutation_solution1(char *pstr, int begin, int

end)512

else

1320}21

}2223//

函式功能 : 求乙個字串某個區間內字元的全排列

24//

函式引數 : pstr為字串,pbegin為開始位置

25//

返回值 : 無

26void permutation_solution2(char *pstr, char *pbegin)

2732

else

3342}43

}44//提供的公共介面

45void permutation(char *pstr)

46

二、去掉重複的全排列的遞迴實現

由於全排列就是從第乙個數字起每個數分別與它後面的數字交換。我們先嘗試加個這樣的判斷——如果乙個數與後面的數字相同那麼這二個數就不交換了。如122,第乙個數與後面交換得212、221。然後122中第二數就不用與第三個數交換了,但對212,它第二個數與第三個數是不相同的,交換之後得到221。與由122中第乙個數與第三個數交換所得的221重複了。所以這個方法不行。

換種思維,對122,第乙個數1與第二個數2交換得到212,然後考慮第乙個數1與第三個數2交換,此時由於第三個數等於第二個數,所以第乙個數不再與第三個數交換。再考慮212,它的第二個數與第三個數交換可以得到解決221。此時全排列生成完畢。

這樣我們也得到了在全排列中去掉重複的規則——去重的全排列就是從第乙個數字起每個數分別與它後面非重複出現的數字交換。下面給出完整**:

1 #include2

using

namespace

std;

3 #include45//

在[nbegin,nend)區間中是否有字元與下標為pend的字元相等

6bool isswap(char* pbegin , char*pend)714

return

true;15

}16void permutation(char* pstr , char *pbegin)

1725

else

2635}36

}37}38

39int main(void)40

問題2:輸入乙個字串,輸出該字串中字元的所有組合。舉個例子,如果輸入abc,它的組合有a、b、c、ab、ac、bc、abc。

思路:同樣是用遞迴求解。可以考慮求長度為n的字串中m個字元的組合,設為c(n,m)。原問題的解即為c(n, 1), c(n, 2),...c(n, n)的總和。對於求c(n, m),從第乙個字元開始掃瞄,每個字元有兩種情況,要麼被選中,要麼不被選中,如果被選中,遞迴求解c(n-1, m-1)。如果未被選中,遞迴求解c(n-1, m)。不管哪種方式,n的值都會減少,遞迴的終止條件n=0或m=0。

1

//函式功能 : 從乙個字串中選m個元素2//

函式引數 : pstr為字串, m為選的元素個數, result為選中的3//

返回值 : 無

4void combination_m(char *pstr, int m, vector &result)515

//選擇這個元素

16 result.push_back(*pstr);

17 combination_m(pstr + 1, m - 1

, result);

18result.pop_back();

19//

不選擇這個元素

20 combination_m(pstr + 1

, m, result);21}

22//

函式功能 : 求乙個字串的組合

23//

函式引數 : pstr為字串

24//

返回值 : 無

25void combination(char *pstr)

2635 }

問題3:打靶問題。乙個射擊運動員打靶,靶一共有10環,連開10 槍打中90環的可能性有多少?

思路:這道題的思路與字串的組合很像,用遞迴解決。一次射擊有11種可能,命中1環至10環,或脫靶。

1

//函式功能 : 求解number次打中sum環的種數2//

函式引數 : number為打靶次數,sum為需要命中的環數,result用來儲存中間結果,total記錄種數 3//

返回值 : 無

4void shootproblem_solution1(int number, int sum, vector &result, int *total)518

else

19return;20

}21for(unsigned i = 0; i <= 10; i++) //

命中0-10環

2227}28

//提供的公共介面

29void shootproblem(int number, int

sum)

30

字串排列

在網上看到了乙個操作字串的題目,該題為 字串排列。大概意思是列出字串中所有字元的所有組合並且輸出無重複。自己做了一下,這裡分享該題的思路,和做法。自我覺得實現的有些麻煩 歡迎指點。問題輸入乙個字串,列印出該字串中字元的所有排列。輸入 字串abc。輸出 列印出由字元a,b,c所能排列出來的所有字串ab...

字串排列

輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。第一種方法 字串拼接 function permutate str else return result console.log pe...

字串的排列

題目 輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串 abc,則輸出由字元a b c所能排列出來的所有字串 abc acb bac bca cab和 cba。分析 這是一道很好的考查對遞迴理解的程式設計題,因此在過去一年中頻繁出現在各大公司的面試 筆試題中。我們以三個字元 abc為例來分析...