排列组合

来源:互联网 发布:桌面日历 知乎 编辑:程序博客网 时间:2024/06/02 07:51

排列组合问题:

1. 字符串全排列(permutation)       转自:http://www.cnblogs.com/sujz/archive/2011/06/16/2082831.html

问题:给定字符串S,生成该字符串的全排列。
方法1:依次从字符串中取出一个字符作为最终排列的第一个字符,对剩余字符组成的字符串生成全排列,最终结果为取出的字符和剩余子串全排列的组合。
#include <iostream>#include <string>using namespace std; void permute1(string prefix, string str){    if(str.length() == 0)        cout << prefix << endl;    else    {        for(int i = 0; i < str.length(); i++)            permute1(prefix+str[i], str.substr(0,i)+str.substr(i+1,str.length()));    }} void permute1(string s){    permute1("",s);} int main(){    //method1, unable to remove duplicate permutations.    cout << "method1" << endl;    permute1("ABA");}
优点:该方法易于理解,但无法移除重复的排列,如:s="ABA",会生成两个“AAB”。

方法2:利用交换的思想,具体见实例,但该方法不如方法1容易理解。


#include <iostream>#include <string>#include <cstdio>using namespace std;void swap(char* x, char* y){    char tmp;    tmp = *x;    *x = *y;    *y = tmp;} /* Function to print permutations of string   This function takes three parameters:   1. String   2. Starting index of the string   3. Ending index of the string. */void permute(char *a, int i, int n){   int j;   if (i == n)     printf("%s\n", a);   else   {        for (j = i; j <= n; j++)       {          if(a[i] == a[j] && j != i)  //为避免生成重复排列,当不同位置的字符相同时不再交换           continue;          swap((a+i), (a+j));          permute(a, i+1, n);          swap((a+i), (a+j)); //backtrack       }   }}  int main(){    //method2    cout << "method2" << endl;    char a[] = "ABA";    permute(a,0,2);    return 0;}
两种方法的生成结果:
method1:
ABA
AAB
BAA
BAA
AAB

ABA

method2:

ABA
AAB
BAA

请按任意键继续. . .

2. 组合  转自:http://www.cnblogs.com/GoAhead/archive/2012/05/30/2526563.html

方法:依次递归地对所有的组合形式进行枚举,从一个字符到n个字符。

对于m个字符的组合,遍历n个字符,决定是否取当前的字符,一直取到足够m个为止,即遍历所有的取法。

#include <iostream>#include <stack>#include <vector>using namespace std;// 函数功能 : 从一个字符串中选m个元素// 函数参数 : pStr为字符串, m为选的元素个数, result为选中的// 返回值 :   无void Combination_m(char *pStr, int m, vector<char> &result){    if(pStr == NULL || (*pStr == '\0'&& m != 0))        return;    if(m == 0) // 递归终止条件    {        for(unsigned i = 0; i < result.size(); i++)            cout << result[i];        cout << endl;        return;    }    // 选择这个元素    result.push_back(*pStr);    Combination_m(pStr + 1, m - 1, result);    result.pop_back();    // 不选择这个元素    Combination_m(pStr + 1, m, result);}// 函数功能 : 求一个字符串的组合// 函数参数 : pStr为字符串// 返回值 :   无void Combination(char *pStr){    if(pStr == NULL || *pStr == '\0')        return;    int number = strlen(pStr);    for( int i = 1; i <= number; i++)    {        vector<char> result;        Combination_m(pStr, i, result);    }}int main(){    char str[] = {'A', 'B', 'A', '\0'};    Combination(str);    return 0;}

结果:

A
B
A
AB
AA
BA
ABA

问题:由于是组合,因此字符串中不能存在相同的字符,如若存在,则需要将他们当做不同的值对待,即不同位置上的相同字符认为是不同的字符。

注: 想要去除重复组合,在进行之前就应该将字符串中的重复字符筛选掉。