我有一个函数接收n和k来创建n选择k的所有可能的排列,虽然它适用于大多数组合,如5选择3或3选择2,它不适用于其他像4选择2我需要一些帮助来发现和理解这个bug。谢谢你的期待。
功能:
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
答案 0 :(得分:7)
前k个值重复n-k阶乘时间。这是一种避免重复的简单但有效的方法:
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(来自https://stackoverflow.com/a/2616837/951890)
可以更简单,更有效地使用它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()));
}
这里的技巧是要意识到最后的排列只是第一个排列的反转,所以通过反转最后的n-k个元素,你会自动跳到这些元素的最后一个排列。
答案 1 :(得分:2)
您可以使用以下内容:
template <typename T>
void Combination(const std::vector<T>& v, std::size_t count)
{
assert(count <= v.size());
std::vector<bool> bitset(v.size() - count, 0);
bitset.resize(v.size(), 1);
do {
for (std::size_t i = 0; i != v.size(); ++i) {
if (bitset[i]) {
std::cout << v[i] << " ";
}
}
std::cout << std::endl;
} while (std::next_permutation(bitset.begin(), bitset.end()));
}
答案 2 :(得分:1)
你输出每个n的前k个成员!排列。 4! = 24个排列。前两个排列是
1,2,3,4
1,2,4,3
你有1,2和1,2
要获得组合(4,2),您可以使用矢量
{0,0,1,1}
置换它,并输出1的索引