字符串的组合

题目:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有abcabacbcabc

分析:在本系列博客的第28题《字符串的排列》中,我们详细讨论了如何用递归的思路求字符串的排列。同样,本题也可以用递归的思路来求字符串的组合。

假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;而是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。下面是这种思路的参考代码:

 

 1 void Combination(char* str)
 2 {
 3     if(str == NULL)
 4         return;
 5  
 6     int length = strlen(str);
 7     vector<char> result;
 8     for(int i = 1; i <= length; ++ i)
 9     {
10         Combination(str, i, result);
11     }
12 }
13  
14 void Combination(char* str, int number, vector<char>& result)
15 {
16     if(number == 0)
17     {
18         vector<char>::iterator iter = result.begin();
19         for(; iter < result.end(); ++ iter)
20             printf("%c", *iter);
21         printf("\n");
22  
23         return;
24     }
25  
26     if(*str == '\0')
27         return;
28  
29     result.push_back(*str);
30     Combination(str + 1, number - 1, result);
31     result.pop_back();
32  
33     Combination(str + 1, number, result);
34 }

 

              由于组合可以是1个字符的组合,2个字符的字符……一直到n个字符的组合,因此在函数void Combination(char* string),我们需要一个for循环。另外,我们一个vector来存放选择放进组合里的字符。

 

以上来自何海涛博客

 

其中,Combination函数里面可以再加一个条件,限制无效的后续步骤,如下面8-11行所示

 1 void Combination(char *str, int number, vector<char>& result)
 2 {
 3     ......
 4  
 5     if(*str == '\0')
 6         return;
 7     
 8     if (number>strlen(str))
 9     {
10         return;
11     }
12 
13     ......
14 }

 

另外,根据该博客后面的跟帖回复,整理了一些其他算法。

1.用一个数组,模拟2进制加法器,某一个为1,则取对应的字符,若为0则不取,就能够实现字符组合。也可以不用数组。设有n个字符。

int num 从 1 自增到 2^n -1, 将num右移i位,跟1做按位&操作,即可判断第i个字符取还是不取。

 

 1 void Combination1(char *str, int number)
 2 {
 3     if (number==0)
 4     {
 5         return;
 6     }
 7 
 8     while(number && *str!='\0')
 9     {
10         if (number&1)
11         {
12             cout<<*str;
13         }
14         str++;
15         number >>= 1;
16     }
17 
18     cout << endl;
19 }
20 void OutputCombination1(char *str)
21 {
22     if (str==NULL)
23     {
24         return;
25     }
26 
27     int len = strlen(str);
28     int kinds = (1<<len)-1;
29     for(int i=1;i<=kinds;i++)
30     {
31         Combination1(str,i);
32     }
33 }

 

2.下面的代码也可以避免无效递归

 

 1 void Combination2(char* str, vector<char>& result)
 2 {
 3     if(*str == '\0')
 4     {
 5         vector<char>::iterator iter = result.begin();
 6         for(; iter < result.end(); ++ iter)
 7             printf("%c", *iter);
 8         printf("\n");
 9         return;
10     }
11     result.push_back(*str);
12     Combination2(str + 1, result);
13     result.pop_back();
14     Combination2(str+1, result);
15 }
16 
17 void OutputCombination2(char *str)
18 {
19     if (str==NULL)
20     {
21         return;
22     }
23 
24     vector<char> result;
25 
26     Combination2(str,result);
27 }

 

 

 

 

posted @ 2012-07-03 16:29  wolenski  阅读(315)  评论(0编辑  收藏  举报