【发布时间】:2010-10-02 07:00:54
【问题描述】:
我需要通过选择一些元素来生成字符串的所有排列。就像我的字符串是 "abc" 输出将是 { a,b,c,ab,ba,ac,ca,bc,cb,abc,acb,bac,bca,cab,cba }。
我想到了一个基本算法,在该算法中,我生成所有可能的“abc”组合,即 {a,b,c,ab,ac,bc,abc},然后将它们全部置换。
那么是否有任何有效的置换算法,通过它我可以生成具有不同大小的所有可能的置换。
我为此编写的代码是:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
using namespace std;
int permuteCount = 1;
int compare (const void * a, const void * b)
{
return ( *(char*)a - *(char*)b);
}
void permute(char *str, int start, int end)
{
// cout<<"before sort : "<<str;
// cout<<"after sort : "<<str;
do
{
cout<<permuteCount<<")"<<str<<endl;
permuteCount++;
}while( next_permutation(str+start,str+end) );
}
void generateAllCombinations( char* str)
{
int n, k, i, j, c;
n = strlen(str);
map<string,int> combinationMap;
for( k =1; k<=n; k++)
{
char tempStr[20];
int index =0;
for (i=0; i<(1<<n); i++) {
index =0;
for (j=0,c=0; j<32; j++) if (i & (1<<j)) c++;
if (c == k) {
for (j=0;j<32; j++)
if (i & (1<<j))
tempStr[ index++] = str[j];
tempStr[index] = '\0';
qsort (tempStr, index, sizeof(char), compare);
if( combinationMap.find(tempStr) == combinationMap.end() )
{
// cout<<"comb : "<<tempStr<<endl;
//cout<<"unique comb : \n";
combinationMap[tempStr] = 1;
permute(tempStr,0,k);
} /*
else
{
cout<<"duplicated comb : "<<tempStr<<endl;
}*/
}
}
}
}
int main () {
char str[20];
cin>>str;
generateAllCombinations(str);
cin>>str;
}
我需要使用哈希来避免相同的组合,所以请告诉我如何使这个算法更好。
谢谢, GG
【问题讨论】:
-
我没有阅读您的代码,但您的口头描述听起来正确:使用 [en.wikipedia.org/wiki/Power_set] 和排列组合。要枚举 幂集,请考虑增加一个二进制数,其中每个“数字”对应于选择输入元素以出现在输出中的次数。对于输入集中的重复元素,“二进制”数的某些“数字”将变为三进制,即该元素的重复计数。
-
请注意,对于长度为
N的字符串,在最坏的情况下(如果所有字符都不同)和每个由L组成的子集,您将拥有2^N-1不同的非空子集字符,您将拥有L!排列。
标签: c++ algorithm permutation combinations