【问题标题】:To generate a subset of size n one by one to reduce the complexity?一个一个地生成一个大小为n的子集来降低复杂度?
【发布时间】:2011-10-17 13:41:53
【问题描述】:
void AlgoMMPCbar::subs(const std::vector<unsigned int>& org, const std::vector<unsigned int>& pre, size_t k, size_t n, SubSets& c){
   if (n <= 1) {
    for(size_t i = k; i < org.size(); i++){
        std::vector<unsigned int> v(pre);// instead of printing...
        v.push_back(org.at(i));
        c.push_back(v);
    }
} else {
    size_t n1 = n - 1;
    for(size_t i = k; i != org.size() - n1; i++){   // 
        std::vector<unsigned int> s(pre);
        s.push_back(org.at(i));
        subs(org,s,i+1,n1,c);
    }
}
}
void AlgoMMPCbar::computeSubSets(const std::vector<unsigned int>& org, size_t& n, SubSets& c){
 c.clear(); // clear previous data

std::vector<unsigned int> pre;
pre.reserve(n+1); // for performance
    if (n==0)
      c.push_back(pre);
else
        subs(org,pre,0, n, c); 
}

上述代码用于生成大小为 n 的子集以供进一步测试/处理。但我从不需要测试所有这些生成的子集(在最坏的情况下它会检查它们)。该程序的主要耗时部分是子集生成。现在我想转换上述功能以一个一个地生成子集(不是一次全部生成,所以我可以随时停止进一步的子集生成)。

请分享您的专业知识,将上述功能转换为子集.next() 等函数,以节省计算时间。

提前致谢。

【问题讨论】:

    标签: c++ subset


    【解决方案1】:

    say ind 以递增顺序维护子集中元素的索引,即

    ind[0] < ind[1] < ... < ind[n-1]
    

    找到最小的j

    j == n-1 || ind[j] + 1 < ind[j+1]
    

    你可以通过

    进入下一个子集
    ind[j]++
    ind[0] = 0; ind[1] = 1; ... ind[j-1] = j-1
    

    请注意,新的ind 数组仍处于排序状态。你可以很容易地从

    开始
    ind[] = [0, 1, ..., n-1]
    

    您将生成所有迭代上述过程的子集。如果您在上面使用一些技巧来“维护”j 的值而不是进行线性搜索,那么您可以获得快速代码。

    【讨论】:

      【解决方案2】:

      你可以让你的subs 函数返回一个bool。在ifn&lt;=1 分支中,您可以运行相应的检查,如果当前子集匹配,则保存并返回true。在另一个分支中,您将subs 调用替换为if (subs(..)) return true;。最后添加return false。 如果您可能需要多个子集,我不知道应该怎么做,而且您不知道到底有多少合适的子集。

      【讨论】:

      • 生成的子集将用于独立性测试,如果发现子集(i)的独立性,则无需检查更多子集。如果我首先生成所有子集然后开始测试,则需要很多时间。所以,我想一一生成子集以节省时间。
      【解决方案3】:

      我会创建某种排序状态向量并按字典顺序逐一遍历它。因此,如果您有一组M 元素并且您想要大小为n 的子集,那么您将拥有一个与所选索引相对应的向量n 整数。然后你创建一个算法next_subset(std::vector&lt;bool&gt; &amp;) 得到下一个子集。例如,对于 5 个大小为 3 的子集:

      1 2 3
      1 2 4
      1 2 5
      1 3 4
      1 3 5
      1 4 5
      2 3 4
      2 3 5
      2 4 5
      3 4 5
      

      我相信你可以发现模式(增加最后一个位置;如果它在最后,将它移回并增加最后两个位置,等等)。

      如果您想提高一点效率,您可以将迭代器存储到原始容器中,如果容器不是随机访问的,则可以存储整数和迭代器对。

      【讨论】:

      • 是的,我已经在逐步生成子集,例如对于 n=1, n=2 ...现在,我想一个一个地生成每个元素。 “如果你想提高一点效率,你可以将迭代器存储到你的原始容器中,或者如果容器不是随机访问的,则可以存储整数和迭代器对。”你能给我一个代码示例吗?谢谢
      • 好吧,假设你有一个std::vector&lt;T&gt; TheSet;。然后你可以创建一个 std::vector&lt;std::vector&lt;T&gt;::const_iterator&gt;n 迭代器,并使用从 TheSet.begin() 到每个迭代器的距离作为索引......如果你没有向量,你可以创建一个向量,比如说,@987654330 @ 用于索引。
      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      相关资源
      最近更新 更多