C++ 递归生成给定子集大小(C+;+;)的所有组合
遵守以下代码:C++ 递归生成给定子集大小(C+;+;)的所有组合,c++,algorithm,c++11,recursion,combinations,C++,Algorithm,C++11,Recursion,Combinations,遵守以下代码: #include <vector> #include <iostream> #include <string> template <typename T> void print_2d_vector(std::vector<std::vector<T>>& v) { for(int i = 0; i < v.size(); i++) { std::cout << "{
#include <vector>
#include <iostream>
#include <string>
template <typename T>
void print_2d_vector(std::vector<std::vector<T>>& v)
{
for(int i = 0; i < v.size(); i++)
{
std::cout << "{";
for(int j = 0; j < v[i].size(); j++)
{
std::cout << v[i][j];
if(j != v[i].size() - 1)
{
std::cout << ", ";
}
}
std::cout << "}\n";
}
}
template <typename T>
struct permcomb2
{
std::vector<std::vector<T>> end_set;
std::vector<T>* data;
permcomb2(std::vector<T>& param) : data(¶m) {}
void helpfunc(std::vector<T>& seen, int depth)
{
if(depth == 0)
{
end_set.push_back(seen);
}
else
{
for(int i = 0; i < (*data).size(); i++)
{
seen.push_back((*data)[i]);
helpfunc(seen, depth - 1);
seen.pop_back();
}
}
}
};
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size)
{
permcomb2<T> helpstruct(data);
std::vector<T> empty {};
helpstruct.helpfunc(empty, subset_size);
return helpstruct.end_set;
}
using namespace std;
int main()
{
std::vector<std::string> flavors {"Vanilla", "Chocolate", "Strawberry"};
auto a1 = permtest(flavors, 2);
cout << "Return all combinations with repetition\n";
print_2d_vector(a1);
return 0;
}
请注意,这段代码并没有实现它声称的功能!它不是返回重复给定子集大小的所有组合(目标),而是返回重复给定子集大小的所有排列。当然,获得组合的一种方法是像我所做的那样生成所有排列,然后循环删除除一个以外的所有相互排列。但我相信这绝对不是最有效的方法
我见过使用嵌套for循环来实现这一点的方法,但这些方法假定子集的大小是提前知道的。我试图将其推广到任何子集大小,因此我尝试递归地进行。问题是,我不太确定如何更改递归“helpfunc”,以便以高效的方式生成所有组合
仅澄清一下,预期产出如下:
Return all combinations with repetition
{Vanilla, Vanilla}
{Vanilla, Chocolate}
{Vanilla, Strawberry}
{Chocolate, Chocolate}
{Chocolate, Strawberry}
{Strawberry, Strawberry}
那么,如何更改代码以获得所有重复的组合,而不是以高效的方式排列?您可以考虑通过嵌套for循环来解决此问题,其中每个循环的计数器从上一个索引变为
数据大小
for (int i = 0; i < data.size(); i++) {
for (int j = i; j < data.size(); j++) {
for (int k = j; k < data.size(); k++) {
// etc...
}
}
确保helpfunc循环从我们所在的索引开始,并且只考虑前面的索引。后面的那些我们不想要,因为它们只是复制品
#include <vector>
#include <iostream>
#include <string>
template <typename T>
void print_2d_vector(std::vector<std::vector<T>>& v)
{
for(int i = 0; i < v.size(); i++)
{
std::cout << "{";
for(int j = 0; j < v[i].size(); j++)
{
std::cout << v[i][j];
if(j != v[i].size() - 1)
{
sizetd::cout << ", ";
}
}
std::cout << "}\n";
}
}
template <typename T>
struct permcomb2
{
std::vector<std::vector<T>> end_set;
std::vector<T>& data;
permcomb2(std::vector<T>& param) : data(param) {}
void helpfunc(std::vector<T>& seen, int depth, int current) // Add one more param for the starting depth of our recursive calls
{
if(depth == 0)
{
end_set.push_back(seen);
}
else
{
for(int i = current; i < data.size(); i++) // Set the loop to start at given value
{
seen.push_back(data[i]);
helpfunc(seen, depth - 1, i);
seen.pop_back();
}
}
}
};
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size)
{
permcomb2<T> helpstruct(data);
std::vector<T> empty {};
helpstruct.helpfunc(empty, subset_size, 0); // Initialize the function at depth 0
return helpstruct.end_set;
}
using namespace std;
int main()
{
std::vector<std::string> flavors {"Vanilla", "Chocolate", "Strawberry"};
auto a1 = permtest(flavors, 2);
cout << "Return all combinations with repetition\n";
print_2d_vector(a1);
return 0;
}
#包括
#包括
#包括
模板
无效打印\u 2d\u矢量(标准::矢量和v)
{
对于(int i=0;i STD::CUT考虑(int i=0;i<10;++i)为(int j= i;j<10;++j){cout@chearsandhth.-Alf这只适用于子集_size=2
。输出顺序重要吗?@JonDeaton:这是一个正确的观察结果。你认为你可以将其推广到其他大小吗?@chearsandhth.-Alf我想是的…我正在研究一个我认为可以推广的解决方案。我们拭目以待。
template <class T>
void solution(std::vector<T>& data, std::vector<std::vector<T>>& sol, int subset_size, int start=0, int depth=0) {
if (depth == subset_size) return;
// Assume that the last element of sol is a base vector
// on which to append the data elements after "start"
std::vector<T> base = sol.back();
// create (data.size() - start) number of vectors, each of which is the base vector (above)
// plus each element of the data after the specified starting index
for (int i = start; i < data.size(); ++i) {
sol.back().push_back(data[i]); // Append i'th data element to base
solution(data, sol, subset_size, i, depth + 1); // Recurse, extending the new base
if (i < data.size() - 1) sol.push_back(base); // Append another base for the next iteration
}
}
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size) {
std::vector<std::vector<T>> solution_set;
solution_set.push_back(std::vector<T>());
solution(data, solution_set, subset_size);
return solution_set;
}
#include <vector>
#include <iostream>
#include <string>
template <typename T>
void print_2d_vector(std::vector<std::vector<T>>& v)
{
for(int i = 0; i < v.size(); i++)
{
std::cout << "{";
for(int j = 0; j < v[i].size(); j++)
{
std::cout << v[i][j];
if(j != v[i].size() - 1)
{
sizetd::cout << ", ";
}
}
std::cout << "}\n";
}
}
template <typename T>
struct permcomb2
{
std::vector<std::vector<T>> end_set;
std::vector<T>& data;
permcomb2(std::vector<T>& param) : data(param) {}
void helpfunc(std::vector<T>& seen, int depth, int current) // Add one more param for the starting depth of our recursive calls
{
if(depth == 0)
{
end_set.push_back(seen);
}
else
{
for(int i = current; i < data.size(); i++) // Set the loop to start at given value
{
seen.push_back(data[i]);
helpfunc(seen, depth - 1, i);
seen.pop_back();
}
}
}
};
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size)
{
permcomb2<T> helpstruct(data);
std::vector<T> empty {};
helpstruct.helpfunc(empty, subset_size, 0); // Initialize the function at depth 0
return helpstruct.end_set;
}
using namespace std;
int main()
{
std::vector<std::string> flavors {"Vanilla", "Chocolate", "Strawberry"};
auto a1 = permtest(flavors, 2);
cout << "Return all combinations with repetition\n";
print_2d_vector(a1);
return 0;
}