通过选择部分或全部字符生成所有排列的算法
我需要通过选择一些元素来生成字符串的所有排列。就像如果我的字符串是“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
I need to generate all permutation of a string with selecting some of the elements. Like if my string is "abc" output would be { a,b,c,ab,ba,ac,ca,bc,cb,abc,acb,bac,bca,cab,cba }.
I thought a basic algorithm in which I generate all possible combination of "abc" which are {a,b,c,ab,ac,bc,abc} and then permute all of them.
So is there any efficient permutation algorithm by which I can generate all possible permutation with varying size.
The code I wrote for this is :
#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;
}
I need to use a hash for avoiding same combination, so please let me know how can I make this algorithm better.
Thanks,
GG
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Next_permutation 使用恒定大小,但您可以添加循环来处理变化的大小。或者只是存储在一组中以消除额外的欺骗:
Next_permutation uses a constant size, but you can add a loop to deal with varying size. Or just store in a set to eliminate the extra dupes for you:
我不认为你能写出比现在更快的程序。主要问题是输出大小:它的阶数为 n!*2^n(子集数 * 一个子集的平均排列数),这已经是
> 。 10^9
表示 10 个不同字符的字符串。由于 STL 的
next_permutation
对于如此小的字符串增加了非常有限的复杂性,因此您的程序的时间复杂度已经接近O(output size)
。但你可以让你的程序更简单一些。特别是, for( k =1; k<=n; k++) 循环似乎没有必要:您已经在变量 c 中计算了子集的大小。因此,只需使用
int k = c
而不是if (c == k)
。 (您还需要考虑空子集的情况:i == 0
)编辑
实际上,
n == 10
只有 9864100 个输出(不是~ 10^9
)。尽管如此,我的观点仍然是一样的:你的程序对于每个输出已经只浪费了“O(next_permutation)”时间,这是非常非常少的。I don't think you can write much faster program than you have already. The main problem is the output size: it has order of
n!*2^n
(number of subsets * average number of permutations for one subset), which is already> 10^9
for a string of 10 different characters.Since STL's
next_permutation
adds very limited complexity for such small strings, your program's time complexity is already nearlyO(output size)
.But you can make your program a bit simpler. In particular,
for( k =1; k<=n; k++)
loop seems unnecessary: you already calculate size of subset in variablec
inside. So, just haveint k = c
instead ofif (c == k)
. (You'll also need to consider case of empty subset:i == 0
)edit
Actually, there's only 9864100 outputs for
n == 10
(not~ 10^9
). Still, my point remains the same: your program already wastes only "O(next_permutation)" time for each output, which is very, very little.