在C ++中生成N选择K排列
我有一个函数,接收n和k来创建n选择k的所有可能排列,并且它适用于5选择3或3选择2之类的大多数组合,但不适用于4选择2的其他组合。一些帮助查找和理解该错误。感谢您的光临。
功能:
void PermGenerator(int n, int k)    {    
    int d[] = {1,2,3,4,5,6,7,8,9};  
    sort (d, d+n);  
    cout << "These are the Possible Permutations: " << endl;  
    do  
    {  
        for (int i = 0; i < k; i++)  
        {  
            cout << d[i] << " ";  
            if (i == k-1) cout << endl;  
        }  
    } while (next_permutation(d, d+n));  
}
我正在使用next_permutation函数。cplusplus
当我尝试4选择2时,我应该得到12个排列,相反我得到了:
1 2    1 2   
1 3   
1 3   
1 4   
1 4   
2 1   
2 1     
2 3   
2 3   
2 4   
2 4   
3 1   
3 1   
3 2   
3 2   
3 4   
3 4   
4 1   
4 1   
4 2   
4 2   
4 3   
4 3
而3选择2可完美搭配6种可能的排列方式:
1 2 1 3   
2 1   
2 3   
3 1   
3 2
回答:
前k个值重复nk个阶乘时间。这是避免重复的简单但有效的方法:
int Factorial(int n){
  int result = 1;
  while (n>1) {
    result *= n--;
  }
  return result;
}
void PermGenerator(int n, int k)
{
    std::vector<int> d(n);
    std::iota(d.begin(),d.end(),1);
    cout << "These are the Possible Permutations: " << endl;
    int repeat = Factorial(n-k);
    do
    {
        for (int i = 0; i < k; i++)
        {
            cout << d[i] << " ";
        }
        cout << endl;
        for (int i=1; i!=repeat; ++i)
        {
            next_permutation(d.begin(),d.end());
        }
    } while (next_permutation(d.begin(),d.end()));
}
但是,有一种使用std ::reverse的方法甚至更简单,更有效。
void PermGenerator(int n, int k){
    std::vector<int> d(n);
    std::iota(d.begin(),d.end(),1);
    cout << "These are the Possible Permutations: " << endl;
    do
    {
        for (int i = 0; i < k; i++)
        {
            cout << d[i] << " ";
        }
        cout << endl;
        std::reverse(d.begin()+k,d.end());
    } while (next_permutation(d.begin(),d.end()));
}
这里的技巧是要认识到最后的排列只是第一个排列的反向,因此,通过反转最后的nk个元素,您可以自动跳到这些元素的最后一个排列。
以上是 在C ++中生成N选择K排列 的全部内容, 来源链接: utcz.com/qa/411708.html
