查找给定集合的所有广度优先组合的最有效方法是什么?
E.g: 给定元素集{1,2,4},输出应该如下(并且也按此顺序 - 不一定是数值,但元素值 - 首先输出第1层(一个元素),然后第2层(两个元素),最后是第3层(三个元素)):
1
2
4
1 2
1 4
2 4
1 2 4
答案 0 :(得分:0)
std::vector<std::set<int>> enumerate_all_subsets(const vector <int> &nums) {
std::vector<std::set<int>> result;
for(auto i = 0ull; i < (1 << nums.size()); ++ i) {
std::set<int> elements;
for(auto k = 0; k < nums.size(); ++ k)
if((i >> k) & 1)
elements.insert(nums[k]);
result.push_back(elements);
}
return result;
}
这会迭代一个大小最大为63的向量(如果你的无符号长long是64位)。任何较大的载体都应该重新考虑,因为这需要一段时间,因为这是O(2^n)
。
基本上unsigned long long i
的每个位代表nums
中的位置,是否应该添加到集合中。
答案 1 :(得分:0)
您可以使用std::next_permutation
:
template <typename T, typename F>
void BreadthFirstCombination(const std::vector<T>& v, F f)
{
for (int i = 0; i != v.size() + 1; ++i) {
std::vector<bool> mask(i, true);
mask.resize(v.size(), false);
do {
f(v, mask);
} while (std::prev_permutation(mask.begin(), mask.end()));
}
}
用法也类似:
auto printer = [](const auto&v, const std::vector<bool>& mask)
{
for (std::size_t i = 0; i != v.size(); ++i) {
if (mask[i]) {
std::cout << v[i] << " ";
}
}
std::cout << std::endl;
};
std::vector<int> v = {1, 2, 4};
BreadthFirstCombination(v, printer);
所以进行
的排列如果您想保留空集,请使用i = 1