字符串排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。(有重复字符和没有重复字符)
1.递归实现:(1)递归算法设计的基本思想是将一个难以解决的大问题,分解为一些规模较小的相同问题,以便各个击破,分而治之。其实,上述算法按照以下方式理解更为合适:我们有一字符串为abc,对应的全排列有6种:abc、acb、bca、bac、cab和cba。它可以由下述规则得到:
Abc的全排列可以由下述规律得到:
a + 全排列(bc)
b + 全排列(ac)
c + 全排列(ab)
递归实现有重复字符的字符串全排列:由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。
换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。下面给出完整代码:
1 #include<iostream> 2 using namespace std; 3 #include<assert.h> 4 5 bool IsSwap(char* pBegin , char* pEnd) 6 { 7 char *p; 8 for(p = pBegin ; p < pEnd ; p++) 9 { 10 if(*p == *pEnd) 11 return false; 12 } 13 return true; 14 } 15 void Swap(char *s1,char *s2 ) 16 { 17 char t=*s1; 18 *s1=*s2; 19 *s2=t; 20 } 21 void Permutation(char* pStr, char* pBegin) 22 { 23 assert(pStr && pBegin); 24 25 if(*pBegin == '\0') 26 printf("%s\n",pStr); 27 else 28 { 29 for(char* pCh = pBegin; *pCh != '\0'; pCh++) 30 { 31 if( IsSwap(pBegin,pCh)) 32 { 33 Swap(pBegin,pCh); 34 Permutation(pStr, pBegin+1); 35 Swap(pBegin,pCh); 36 } 37 38 39 } 40 } 41 } 42 43 int main(void) 44 { 45 char str[] = "baa"; 46 Permutation(str,str); 47 system("pause"); 48 return 0; 49 }
递归实现没有重复字符的字符串全排列:
1 #include<iostream> 2 using namespace std; 3 #include<assert.h> 4 5 6 void Swap(char *s1,char *s2 ) 7 { 8 char t=*s1; 9 *s1=*s2; 10 *s2=t; 11 } 12 void Permutation(char* pStr, char* pBegin) 13 { 14 assert(pStr && pBegin); 15 16 if(*pBegin == '\0') 17 printf("%s\n",pStr); 18 else 19 { 20 for(char* pCh = pBegin; *pCh != '\0'; pCh++) 21 { 22 23 Swap(pBegin,pCh); 24 Permutation(pStr, pBegin+1); 25 Swap(pBegin,pCh); 26 27 28 29 } 30 } 31 } 32 33 int main(void) 34 { 35 char str[] = "abc"; 36 Permutation(str,str); 37 system("pause"); 38 return 0; 39 }