字符串组合问题

1.对于给定的字符串,求出所有的排列组合方式
思路:例如,对于“abc”,先确定以a开头,只需要考虑bc的顺序,递归进去求bc的子问题
再交换a和b以b开头得到“bac”,只需考虑ac的顺序,递归求解ac的子问题
最后以c开头,求解ab的顺序,递归求解ab的子问题
注意:在程序实现时,每次确定交换打头的字符后必须将字符串还原,以免影响后面的交换
详细图示:

这里写图片描述

//pStr为待排列的字符串,start为起点,end为排序的末尾+1
void  Permutation(char *pStr,int start,int end){
    if(start==end-1){
        //此时排序结束
        cout<<pStr<<endl;//输出一个排序好的结果
    }else{
        for(int k=start;k<end;k++){
            //1.从start开始确定开头的字符,将字符串后面的所有字符都需要和start所在的字符交换作为首字符
            swap(pStr[k],pStr[start]);
            //2.递归求解相同的子问题,直到待排列的字符串长度为1停止
            Permutation(pStr,start+1,end);
            //3.完成一轮以pStr[k]为开头的字符串排列后需要将交换过的字符还原,以遍下一次直到正确位置继续交换得到新的首字符
             swap(pStr[k],pStr[start]); 
        }

    }
}

2.对于给定的字符串,求出所有的不重复的排列组合方式
思考:和上面的问题类似,就是所给定的字符串可能会有相同的字符,在排列过程中,会产生重复的序列。现在需要进行一次去重处理。需要先将所有的排列组合方式都保存在一个数组或者容器里面,在利用相关去重函数进行处理。代码如下

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
vector<string>   cvec;
void Permutation(char *pStr,int start,int end){
    if(start==end-1){
        char buf[20];
        strcpy(buf,pStr);
        cvec.push_back(buf);
    }
    else
    {
        for(int k=start;k<end;k++){
            swap(pStr[k],pStr[start]);
            Permutation(pStr,start+1,end);
            swap(pStr[k],pStr[start]);
        }
    }
}
int main(){
    char pStr[]="abbc";
    Permutation(pStr,0,4);

    //按照字典序排列
    sort(cvec.begin(),cvec.end());
    //确保唯一性,返回最后一个不重复的下一个位置
    auto end_unique=unique(cvec.begin(),cvec.end());
    //删除重复的元素
    cvec.erase(end_unique,cvec.end());
    cout<<cvec.size()<<endl;

    system("pause");
    return 0;
}

也有网友在进行交换之前先判断以前的序列中是否和当前的字符串相同,若相同就不交换。这种方法也跟好。
3.字符串的子串组合种类
思考:输入一个字符串,输出该字符串中字符的所有组合的问题。举个例子,如果输入”abc”,它的组合有a、b、c、ab、ac、bc、abc。

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
#include<assert.h>

void Combination(char *string ,int number,vector<char> &result);

void Combination(char *string)
{
    assert(string != NULL);
    vector<char> result;
    int i , length = strlen(string);
    for(i = 1 ; i <=2 ; ++i)
        Combination(string , i ,result);
}
void Combination(char *string ,int number , vector<char> &result)
{
    if(number == 0)
    {
        static int num = 1;
        printf("第%d个组合\t",num++);
        vector<char>::iterator iter = result.begin();
        for( ; iter != result.end() ; ++iter)
            printf("%c",*iter);
        printf("\n");
        return ;
    }
    if(*string == '\0')
        return ;
    result.push_back(*string);
    Combination(string + 1 , number - 1 , result);
    result.pop_back();
    Combination(string + 1 , number , result); 
}

int main(void)
{
    char str[] = "abc";
    Combination(str);
    system("pause");
    return 0;
}

注意:上述代码没有加上自己和空字符串!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值