广度优先组合
Breadth First Combination
找到给定集合的所有广度优先组合的最有效方法是什么?
例如:
给定一组元素 {1,2,4},输出应如下所示(也按此顺序 - 不一定是数值,但元素值 - 首先应该输出第 1 层(一个元素),然后是第 2 层(两个元素),最后是第 3 层(三个元素):
1
2
4
1 2
1 4
2 4
1 2 4
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 的向量(如果您的 unsigned long long 是 64 位)。可能应该重新考虑任何更大的向量,因为这需要一段时间,因为这是 O(2^n)
.
基本上 unsigned long long i
的每一位代表 nums
中的一个位置,以及是否应该将其添加到集合中。
您可以使用 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);
所以做
的排列
- 假假假
- 真假假 (-> 100 010 001)
- 真真假 (-> 110 101 011)
- 真真真
如果要保留空集,请从 i = 1
开始循环
找到给定集合的所有广度优先组合的最有效方法是什么?
例如: 给定一组元素 {1,2,4},输出应如下所示(也按此顺序 - 不一定是数值,但元素值 - 首先应该输出第 1 层(一个元素),然后是第 2 层(两个元素),最后是第 3 层(三个元素):
1
2
4
1 2
1 4
2 4
1 2 4
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 的向量(如果您的 unsigned long long 是 64 位)。可能应该重新考虑任何更大的向量,因为这需要一段时间,因为这是 O(2^n)
.
基本上 unsigned long long i
的每一位代表 nums
中的一个位置,以及是否应该将其添加到集合中。
您可以使用 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);
所以做
的排列- 假假假
- 真假假 (-> 100 010 001)
- 真真假 (-> 110 101 011)
- 真真真
如果要保留空集,请从 i = 1