在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

回到顶部