转自:http://blog.csdn.net/ns_code/article/details/26405471
剑指offer上的拓展题目,输入一个字符串,输出该字符串的字符的所有组合,比如输入字符串: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。
思路二:
开辟一个于字符串对应长度的int数组(char数组也可以,而且更节省空间),用该数组模拟二进制的加1操作,则该数组的元素只能为0或1,我们规定如果该数组某个位置处的元素是1,则字符串对应位置处的字符参与组合,如果为0,则字符串对应位置处的字符不参与组合,这样讲该int数组,从全0加到全1,便可得到字符串的全部组合。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
bool increment(char *bindAdd,int len)
{
if(bindAdd==NULL)
return false;
bindAdd[len-1]++;
int i;
for(i=len-1;i>=0;i--)
{
if(bindAdd[i]>=2)
{
if(i==0)
{
bindAdd[i]--;
return false;
}
else{
bindAdd[i]-=2;
bindAdd[i-1]++;
}
}
else
break;
}
return true;
}
void comination(char *str)
{
if(str==NULL)
return;
int len=strlen(str);
char* bindAdd=(char*)malloc(len*sizeof(char));
if(bindAdd==NULL)
exit(EXIT_FAILURE);
memset(bindAdd,0,len*sizeof(char));
while(increment(bindAdd,len))
{
int i;
for(i=0;i<len;i++)
{
if(bindAdd[i]==1)
putchar(str[i]);
}
putchar('\n');
}
free(bindAdd);
bindAdd=NULL;
}
int main()
{
char str[10];
while(gets(str))
comination(str);
return 0;
}
结果: