本来是想在网上搜索下现成的,结果看到一堆想吐的,尼玛啊,什么递归了,什么回溯了。无语!难道就不能负责任点,搜索下相关算法,然后,好好的实现下?又不是有多难的算法!最可恶的是,这些人还zhuangbility,以为自己写的算法很好,贴出来炫耀,有啥可炫耀的?
数学简单道理
N! <<<< N^N
我把它看成N进制,全部生成一遍,去掉位数有重复的,必然是N!这样的排列算法都比哪些瞎写的好
C(N,K> <<< N^K,同样用N进制,一共K位,那样全生成一遍,去掉不合理的(如必须是升序,或者降序),自然是对的。就这个最浅显的算法,也比这些zhuangbility的人贴的算法强。
给个knuth排列组合书(第四卷)的算法实现(这还是其性能最差的一个)
//在N中选取K个数,[first,last)必须有序
template<typename rand_it,typename T>
void choose(rand_it first,rand_it last,int k,std::vector<std::vector<T> >&out)
{
std::vector<int> assitVec ;
assitVec.resize(k+1);
//std::sort(vec.begin(),vec.end());
//<1>初始化,//需要增加一个哨兵
//std::copy(vec.begin(),vec.begin()+k,assitVec.begin());
assitVec.resize(k+1);
for(int j=0;j<k+1;j++){
assitVec[j]=j;
}
int N=std::distance(first,last);
int bit=0;
int i=0;
assitVec[k]=N;
LOOP:
//<2>判断终止条件
if(assitVec[i] == N){
//结束
return ;
}
//<3>输出辅助数组
out.push_back(std::vector<T>(k));
for(int j=0;j<k;j++)
{
rand_it it = first;
std::advance(it,assitVec[j]);
out.back()[j] = *it;
}
//<4>调整
int flag=0;
while(i<k){
if(assitVec[i] +1 == assitVec[i+1])
{
//需要进一位,当前位恢复原始状态
assitVec[i] = i;
i++;
flag=1;
}
else{
assitVec[i]++;
break;
}
}
if(assitVec[i] == N){
//结束
return ;
}
for(bit=0;bit<i;bit++){
assitVec[bit]=bit;
}
if(flag){
i=0;
}
goto LOOP;
}
上面的迭代器,虽然写的是random_it,但实际上支持output_it就可以了。
仅仅是 std::advance(it,assitVec[j]);这句稍微慢一点,当然实际上可以忽略。
使用如下举例:前提条件 K要小于集合长度
int main(int argc,char*argv[]){
std::vector<int>vec(10);
for(int i=0;i<10;i++){
vec[i]='z'-i;
}
std::vector<std::vector<int> > out;
// std::sort(vec.begin(),vec.end());
choose(vec.begin(),vec.end(),3,out);
printf("%d\n",out.size());
for(int i=0;i<out.size();i++){
for(int j=0;j<out[i].size();j++){
std::cout<<(char)out[i][j]<<",";
}
std::cout<<std::endl;
}
return 0;
}