字符串排列组合算法
第二个算法是我笔试题遇到的,当时没有做出来,在网上看到别人写的算法,感觉太精妙了。就在这里分享出来。
全排列
所谓全排列,就是打印出字符串中全部字符的全部排列。比如输入字符串abc
。则打印出 a、b、c 所能排列出来的全部字符串 abc
、acb
、bac
、bca
、cab
和 cba
。
#include<stdio.h>
#include<string.h>
static int number=0;
void Swap(char *a ,char *b)
{
char temp = *a;
*a = *b;
*b = temp;
}
void AllRange(char* str,int start,int length)
{
if(start == length-1)
{
printf("%s\n",str);
number++;
}
else
{
for(int i=start;i<=length-1;i++)
{
Swap(&str[start],&str[i]);
AllRange(str,start+1,length);
Swap(&str[start],&str[i]);
}
}
}
void Permutation(char* str)
{
if(str == NULL)
return;
AllRange(str,0,strlen(str));
}
void main()
{
char str[] = "abcde";
Permutation(str);
printf("number=%d\n",number);
}
全组合
如果不是求字符的全部排列。而是求字符的全部组合应该怎么办呢?还是输入三个字符 a、b、c。则它们的组合有a
b
c
ab
ac
bc
abc
。当然我们还是能够借鉴全排列的思路,利用问题分解的思路,终于用递归解决。
只是这里介绍一种比較巧妙的思路 —— 基于位图。
如果原有元素 n 个,则终于组合结果是
我们能够用位操作方法:如果元素原本有:a,b,c 三个。则 1 表示取该元素。0 表示不取。故取a
则是001
。取ab
则是011
。
所以一共三位。每一个位上有两个选择 0 和 1。而000
没有意义,所以是
这些结果的位图值都是 1,2…2^n-1。
所以从值 1 到值
001
,010
,011
,100
,101
,110
,111
。相应输出组合结果为:a
,b
,ab
,c
,ac
,bc
,abc
。
因此能够循环 1~2^n-1,然后输出相应代表的组合就可以。有代码例如以下:
#include<stdio.h>
#include<string.h>
static int number=0;
void Combination(char *str)
{
if(str == NULL)
return ;
int len = strlen(str);
int n = 1<<len;
printf("n=%d\n",n);
for(int i=1;i<n;i++) //从 1 循环到 2^len -1
{
for(int j=0;j<len;j++)
{
int temp = i;
if(temp & (1<<j)) //相应位上为1,则输出相应的字符
{
printf("%c",*(str+j));
}
}
number++;
printf("\n");
}
}
void main()
{
char str[] = "abcdef";
Combination(str);
printf("number:%d\n",number);
}
反转字符串
main.c#include<stdio.h> #include<string.h> void print(char *str) { if(*str!='\0') print(str+1); if(*str!='\0') printf("%c",*str); } int main(int argc,char **argv) { char *buff="hello world"; print(buff); printf("\n"); return 0; }