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

剑指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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值