算法之字符串全排列,全组合问题详解------(剑指offer)

    题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印由字符abc所能排列出来的所有字符串abc,acb,bac,bca,cab,cba.

问题解析:

(1)求所有可能出现在第一个位置的字符,即把第一个字符和后面的所有字符进行交换。

(2)固定第一个字符,求后面的排列。

(3)仍然可以把后面的分成第一步和第二步。

以abc 为例:

(1)a    b    c        a和自己进行交换,此时固定a,然后求后面b和c的排列

(2)a    b    c        b和自己进行交换, 此时固定b,求c的排列

(3)a    b    c        c和自己进行交换,固定c,但后面已没有排列,输出

(4)a    c    b        返回(2)b和c进行交换,固定c求后面b的排列,和(3)类似,输出

(5)b    a    c        返回(1)a和b进行交换,固定b求后面的排列

后面的基本操作都类似,最后输出abc    acb    bac    bca    cab    cba

以下是代码:

#include<iostream>

#include<cstdio>

#include<string>

using namespace std;

//字符串全排列

/*将开头第一个字符先与每一个后面的字符进行交换

  固定开头字符,求后面字符组合

  后面字符重复上面的步骤,直到下一个字符为空*/

void Permutation(string &s, int pbegin)

{

        if (s[pbegin] == '\0')

        {

               cout << s << endl;

        }

        for (int pch = pbegin; s[pch] != '\0'; pch++)

        {

               char temp = s[pch];

               s[pch] = s[pbegin];

               s[pbegin] = temp;

               Permutation(s,pbegin+1);

               temp = s[pch];

               s[pch] = s[pbegin];

               s[pbegin] = temp;

        }

}

int main(void)

{

        string s;

        cin >> s;

        Permutation(s,0);

        return 0;

}

全组合

基本思想: 如果输入n个字符,则这n个字符能构成长度为1,2,...,n的组合。在求n个字符的长度为m(1<=m<=n)组合的时候,我们把这n个字符分成两部分:

第一个字符和其余的所有字符。

如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;

如果组合里不包含第一个字符,则下一步在剩余的n-1字符里选取m个字符。

也就是说:我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题。

(1)分别求n-1个字符中长度为m-1的组合

(2)分别求n-1个字符中长度为m的组合。

什么意思呢?

举个栗子:

a    b    c    

n为3,求长度为1的组合

先将a放进去    a    b    c    ,求后面为0的组合,就直接输出a

往后移,将a取出  a   b     c,求后面长度为1的组合

现在移到字符b上(将a不放进去,b在里面),求后面长度为0的组合,直接输出b

往后移b,(将b取出)    c,求后面长度为1的组合

现在移到c上(将b不放进去),求后面长度为0的组合,直接输出c

往后移为空,返回。

后面基本类似。

算法代码:

//全组合

#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);

        //分别求出长度为1,2,...,n的组合

        for (i = 1; i <= length; ++i)           //用for循环分开字符组合

               Combination(string, i, result);

}

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

{

        assert(string != NULL);

        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);

        //string+1表示n-1的字符

        Combination(string + 1, number - 1, result);//把当前第一个字符放到组合之中

        result.pop_back();

        Combination(string + 1, number, result);//把当前第一个字符不放到组合之中

}

int main(void)

{

        char str[] = "aab";

        Combination(str);

        system("pause");

        return 0;

}

参考博客https://www.cnblogs.com/zengshangzhi/p/9305534.html

猜你喜欢

转载自blog.csdn.net/suoyudong/article/details/88343438