【问题标题】:combinations algorithm组合算法
【发布时间】:2011-01-31 03:46:55
【问题描述】:

我想做简单的排序算法。

给定输入“abcde”,我想要下面的输出。你能告诉我这个算法吗?

arr[0] = "a"
arr[1] = "ab"
arr[2] = "ac"
arr[3] = "ad"
arr[4] = "ae"
arr[5] = "abc"
arr[6] = "abd"
arr[7] = "abe"
...
arr[n] = "abcde"

arr[n+1] = "b"
arr[n+2] = "bc"
arr[n+3] = "bd"
arr[n+4] = "be"
arr[n+5] = "bcd"
arr[n+5] = "bce"
arr[n+5] = "bde"
...
arr[n+m] = "bcde"
...
...

【问题讨论】:

    标签: c++ c combinations


    【解决方案1】:

    您正在寻找一种从数组“生成幂集”的算法。您可以尝试使用 Google 或其他搜索引擎来找到最适合您需求的算法。

    【讨论】:

    • +1 因为有时人们觉得他们需要谷歌搜索但不知道算法的名称。
    【解决方案2】:

    在 C++ 中给出以下例程:

    template <typename Iterator>
    bool next_combination(const Iterator first, Iterator k, const Iterator last)
    {
       /* Credits: Mark Nelson http://marknelson.us */
       if ((first == last) || (first == k) || (last == k))
          return false;
       Iterator i1 = first;
       Iterator i2 = last;
       ++i1;
       if (last == i1)
          return false;
       i1 = last;
       --i1;
       i1 = k;
       --i2;
       while (first != i1)
       {
          if (*--i1 < *i2)
          {
             Iterator j = k;
             while (!(*i1 < *j)) ++j;
             std::iter_swap(i1,j);
             ++i1;
             ++j;
             i2 = k;
             std::rotate(i1,j,last);
             while (last != j)
             {
                ++j;
                ++i2;
             }
             std::rotate(k,i2,last);
             return true;
          }
       }
       std::rotate(first,k,last);
       return false;
    }
    

    然后您可以继续执行以下操作:

    std::string s = "abcde";
    for(std::size_t i = 1; i != s.size(); ++i)
    {
       do
       {
          std::cout << std::string(s.begin(),s.begin() + i) << std::endl;
       }
       while(next_combination(s.begin(),s.begin() + i,s.end()));
    }
    

    注意:您应该会看到 2^n-1 个组合,其中 n 是数组或字符串的长度。

    【讨论】:

    • 您引用的网站似乎不包含此程序。
    • 你应该再努力一点:marknelson.us/2002/03/01/next-permutation 在页面上搜索词:“next_combination”
    • @Beh:不正确。我将 next_combination 放在搜索栏中,它会自动完成,并且没有返回任何结果 marknelson.us/… 。我怀疑你用的是谷歌。在任何情况下,该页面包含该程序,只有 cmets 具有指向各种类似程序的链接。我看到的最接近解释的是codeguru.com/cpp/cpp/algorithms/combinations/article.php/c5117,但它没有这个特定的代码。转发某人的代码后,您应该提供更清晰的学分。
    【解决方案3】:

    您正在描述power set。下面是一些 C++ 代码:

    #include <vector>
    #include <string>
    #include <algorithm>
    #include <functional>
    using namespace std;
    
    vector< string > string_powerset( string const &in ) {
        vector< string > result(1); // start output with one empty string
        result.reserve( 1 << in.size() ); // output size = 2^( in.size() )
        if ( result.capacity() != 1<<in.size() ) throw range_error( "too big" );
    
        for ( string::const_iterator it = in.begin(); it != in.end(); ++ it ) {
            size_t middle = result.size(); // duplicate what we have so far
            result.insert( result.end(), result.begin(), result.end() );
    
              // append current character onto duplicated output
            for_each( result.begin() + middle, result.end(),
               bind2nd( mem_fun_ref( &string::push_back ), * it ) );
        }
        return result;
    }
    

    测试工作:v)。范围检查不是最好的,但无论如何。

    由于 powerset 呈指数增长,此代码容易溢出,因此您应该只传递短字符串。另一个发布的答案通过一次生成和返回一个字符串来避免这个问题。但是,这更容易理解,并且使用更大且更混乱的代码段将是过早的优化,除非您实际上遇到溢出问题。

    编辑:我是wrote up a next_subset answer,它看起来不像本的。

    【讨论】:

    • 我投了你一票,因为你很好地利用了 STL。但有些事情我会批评,但这些都是风格问题。首先,using namespace std 不是一个好主意。其次,将移位运算符用于 2 的幂有点不清楚。第三,为什么是string const &amp; in 而不是const string &amp; in(我没见过)?
    • 1.我觉得通过解决问题并编写所有这些代码,我获得了一些懒惰。 OP 不会让我觉得有大型代码库问题。这不是头文件。 2. 所以我评论了它,也注意到溢出情况的沮丧。 3.我的const风格比较统一。 const 附加到 preceding 标识符或修饰符,除非 const 是该类型的第一个标记。我避免特殊情况。另外,先说string“可以更快地开始工作。”
    • 为了记录,这个答案现在有 3 个赞成票和 3 个反对票。没有反对者发表评论。
    • 我赞成你,因为他们反对。我自己使用的是你提出的风格,如果有人告诉我他以前从未见过这个,我只是不知道该说什么。
    猜你喜欢
    • 2013-03-10
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 2014-08-29
    相关资源
    最近更新 更多