C++中一系列数字的组合
Combinations in a range of numbers in C++
我想构建一个C++程序,根据N因子所取元素的数量来显示所有可能的组合。
让我们假设一个向量vec[6],上面有元素1 2 3 4 5 6。
使用组合公式,6!/4.(6-4)!=15种可能性
我想生成一个函数,它给出所有15种可能性的结果,取4乘4,不重复,例如:
1 2 3 4
1 2 3 5
1 2 3 6
2 3 4 5
等等…
我现在使用这个代码,但我想使用向量(v[6])中的数字。
#include <algorithm>
#include <iostream>
#include <string>
void comb(int N, int K)
{
std::string bitmask(K, 1); // K leading 1's
bitmask.resize(N, 0); // N-K trailing 0's
// print integers and permute bitmask
do {
for (int i = 0; i < N; ++i) // [0..N-1] integers
{
if (bitmask[i]) std::cout << " " << i;
}
std::cout << std::endl;
} while (std::prev_permutation(bitmask.begin(), bitmask.end()));
}
int main()
{
comb(6, 4);
}
你们能帮我一下吗?我想知道在哪里可以更改代码,这样我就可以使用自己的矢量了。
我正在生成这个向量v[i],并用冒泡排序对其进行排序,如下所示:
void order (int d[], int n){
int i, j;
for (i = 1; i < n; i++)
for (j = 0; j < n-1; j++)
if (d[j] > d[j+1])
swap (d[j],d[j+1]);
for (i = 0; i < n; i++)
cout << d[i] << " ";
}
排序之后,我想把向量放入comb函数中。我怎样才能使它成为可能?
这里有一个C++14解决方案,它使用一个免费的开源库来完成这项工作:
#include "combinations"
#include <iomanip>
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6};
int state = 0;
for_each_combination(v.begin(), v.begin() + 4, v.end(),
[&state](auto first, auto last)
{
std::cout << std::setw(2) << ++state << " : ";
while (true)
{
std::cout << *first;
if (++first == last)
break;
std::cout << ' ';
}
std::cout << 'n';
return false;
});
}
该输出:
1 : 1 2 3 4
2 : 1 2 3 5
3 : 1 2 3 6
4 : 1 2 4 5
5 : 1 2 4 6
6 : 1 2 5 6
7 : 1 3 4 5
8 : 1 3 4 6
9 : 1 3 5 6
10 : 1 4 5 6
11 : 2 3 4 5
12 : 2 3 4 6
13 : 2 3 5 6
14 : 2 4 5 6
15 : 3 4 5 6
可以从上面的链接复制/粘贴库的源代码,并检查其工作方式。与使用std::prev_permutation
的解决方案相比,此库的性能非常高。这个函数的实现相对简单,但库也包含更多的功能,这些功能的实现越来越复杂(但同样易于使用):
template <class BidirIter, class Function>
Function
for_each_combination(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
图书馆有几个令人愉快的功能,包括:
- 您的输入序列(
vector
或其他)不需要排序 - 您可以随时通过返回
true
提前脱离循环 - 如果您没有提前脱离循环,序列总是返回到其原始状态
- 函子总是接收序列的第一个
k
元素的迭代器,因此如果您告诉函子序列的总长度,也可以对未选择的元素进行操作
可以随意使用该库,或者研究并从其实现中获取所需内容。上面的链接包含类似教程的描述,以及每个函数的详细规范。
从子集S={1,2,3,…,k}开始,这是第一个子集。通过从右边检查元素(从最后一个开始)生成下一个子集,如果可以的话(如果是<N),将其递增,并将其作为下一个子集中返回。如果不能递增,请查看左侧的元素,直到找到一个可以递增的元素。将其递增,然后从该点开始按顺序将元素设置到右侧。以下是{1,2,3,4,5}的3个元素子集(N=5,k=3,有10个子集):
{1,2,3}、{1,2,4}、{1,3,4}、{1,3,5}、{1,4,5}、{1,4,5}、{2,3,4}、{2,3,5}
#include <iostream>
#include <vector>
std::ostream& operator<<(std::ostream& o, std::vector<int>& a)
{
o << "{";
for (std::vector<int>::const_iterator it = a.begin(); it != a.end(); ++it) {
o << *it;
if (it + 1 < a.end()) o << ",";
}
return o << "}";
}
int main()
{
const int N = 7;
const int k = 4;
std::vector<int> A(k);
// initialize
for (int i = 0; i < k; ++i) {
A[i] = i + 1;
}
std::cout << A << std::endl;
int h = 0;
bool done = false;
do {
++A[k-h-1];
for (int t = k - h; t < k; ++t) {
A[t] = A[t-1] + 1;
}
if (A[k-h-1] < N - h) {
// last element can be incremented, stay there...
h = 0;
} else {
// last element at max, look back ...
++h;
}
done = (A[0] == N - k + 1);
std::cout << A << std::endl;
} while (!done);
}
非常简单的递归实现:
struct Combs
{
vector<int> scombs;
template <typename F>
void call_combs(int n, int k, F f)
{
if (k == 0) {
f();
}
else {
scombs.push_back(n - 1);
call_combs(n - 1, k - 1, f);
scombs.resize(scombs.size() - 1);
if (k < n) {
call_combs(n - 1, k, f);
}
}
}
};
...
Combs combs;
const auto& coco = combs.scombs;
combs.call_combs(6, 4, [&coco](){
copy(coco.cbegin(), coco.cend(), ostream_iterator<int>(cout));
cout << endl;
});
- 找到 x^n 的所有组合,并检查它们的总和是否等于一个不包括相同数字的数字
- 如何用数学方式组合数字?
- 如果我们从每个 Y 向量中选择一个值,则 X 数字的每个组合都可能
- 在手臂霓虹灯中有效地重新洗牌和组合 16 个 3 位数字
- 如何在C ++中打印特定位数的位数?例如,总共打印8位数字(小数点之前+之后的组合)
- 如何指示/打印基于斐波那契数字的程序的不同组合
- 如何编写检查 3 个数字组合的函数
- 使用加法,减法和串联将数字组合到给定数字的方式
- 给定数字与重复的组合的算法?C
- 制作需要接受字母和数字组合的密码类型程序
- 设计生成所有 n 位数字组合的递归函数的最佳方法是什么?
- 为循环嵌套的变量快速生成数字组合
- 生成k数字的NCK组合的程序从1到n不等
- 如何有效地将数字矢量列表组合到一个大数字向量中
- 给定分隔成数组元素的数字,如何在 int 中重新组合数字
- 查找存储在一个数组中的数字组合,并将这些组合存储在另一个数组
- 生成每个可能的 7 位数字组合的算法
- 获取C++中数字的所有组合
- 用于检查向量中任何数字组合是否加起来为 int 的函数
- 用数字打印所有可能的组合