广度优先组合

时间:2017-10-17 03:25:40

标签: c++ combinations breadth-first-search

查找给定集合的所有广度优先组合的最有效方法是什么?

E.g: 给定元素集{1,2,4},输出应该如下(并且也按此顺序 - 不一定是数值,但元素值 - 首先输出第1层(一个元素),然后第2层(两个元素),最后是第3层(三个元素)):

1 2 4 1 2 1 4 2 4 1 2 4

2 个答案:

答案 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);

Demo

所以进行

的排列
  • false false false
  • true false false( - &gt; 100 010 001)
  • true true false( - &gt; 110 101 011)
  • true true true

如果您想保留空集,请使用i = 1

开始循环