《剑指Offer》面试题:字符串的组合(不用递归求解)

来源:互联网 发布:linux crontab 权限 编辑:程序博客网 时间:2024/06/05 11:05

剑指offer上的拓展题目

输入一个字符串,输出该字符串的字符的所有组合
比如输入字符串:abc,输出a、b、c、ab、ac、bc、abc。

书上提供的思路如下(递归呀递归,自己不怎么会实现,发现理解递归的精髓还是有一定难度的)

如果输入n个字符,则这n个字符能构成长度为1的组合、长度为2的组合、。。。、长度为n的组合。
在求n个字符的长度m的组合的时候,我们把这n个字符分成两部分:第一个字符和其余的所有字符。如果组合里包含第一个字符,
则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符中选取m个字符。
也就是说,我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题,分别求n-1个字符串中长度为m-1的组合,
以及求n-1个字符的长度为m的组合。这两个子问题都可以用递归来解决。

本博文采用的思路

由于需要输出字符串的所有组合情况,在这里不用递归来进行求解。
这里采用另外一个方法来求解,我们开辟一个与字符串等长的int类型的数组,数组中的元素只能非0即1两种情况,当数组中某位的元素为1时,则字符串中对应的那位参与了组合;如果为0,则字符串对应位置处的字符不参与组合。用数组来模拟二进制加1的操作,当数组中的组合有全0变为全1的时候,就找到了字符串中所有的组合 ,不过这样不是按照字典的顺序输出,如果需要按字典的顺序将这些组合输出,则只需要将这些组合放在一个大的数组中进行保存,然后进行字符串的排序输出即可。

#include<stdio.h>#include<stdlib.h>#include<string.h>/*函数的功能:用数组模拟二进制加1 操作。 */bool increment(int *binaryArr,int len){    if(binaryArr==NULL||len<=0){        return false;    }     //与我们熟悉的二进制类似,最右边为低位,最左边为高位。     binaryArr[len-1]++;    for(int i=len-1;i>=0;i--){        if(binaryArr[i]>=2){            if(i==0){                return false;//最高位产生了进位,则说明已经经历了从全0到全1。             }            else{                binaryArr[i]-=2;                binaryArr[i-1]++;            }         }     }    return true; }void allCombinationInString(char *str){    if(str==NULL)        return ;    int len=strlen(str);    //第一步:开辟与str长度相同的int空间。并初始化为0.    int* binaryArr=(int *)malloc(len*sizeof(int));    if(binaryArr==NULL){        exit(EXIT_FAILURE);    }     memset(binaryArr,0,len*sizeof(int));//初始化为0    while(increment(binaryArr,len)){        for(int i=0;i<len;i++){            if(binaryArr[i]==1){                printf("%c",str[i]);            }        }        printf("\n");    } }int main(void){    char str[10];    while(gets(str)){        allCombinationInString(str);    }    return 0;}

运行结果如下:

0 0