查找字符串向量的r-组合

时间:2014-12-04 15:23:59

标签: c++ algorithm combinations

我试图生成给定字符串列表的所有可能的r组合。例如:

vector<string> original(n);
original[0] = "Brown";
original[1] = "Yellow";
original[2] = "Blue";

在这种情况下,n = 3(3种颜色),例如,如果用户输入r = 2,则程序必须打印:

    >Brown, Yellow
    >Brown, Blue
    >Yellow, Blue

我所谈过的每个人都说要使用next_permutation路线,但这会让我重复(我正在寻找组合,而不是排列.....所以在上面的例子中,在集合之后(黄色,蓝色),(蓝色) ,黄色)不应包括在内)。

3 个答案:

答案 0 :(得分:2)

您可以使用以下内容:

template <typename T>
void Combination(const std::vector<T>& v, std::size_t count)
{
    assert(count <= v.size());
    std::vector<bool> bitset(v.size() - count, 0);
    bitset.resize(v.size(), 1);

    do {
        for (std::size_t i = 0; i != v.size(); ++i) {
            if (bitset[i]) {
                std::cout << v[i] << " ";
            }
        }
        std::cout << std::endl;
    } while (std::next_permutation(bitset.begin(), bitset.end()));
}

Live example

答案 1 :(得分:0)

尝试以下步骤:

1)创建一系列3位。

2)由于r为2,因此将最右边的两位初始化为1。

3)输出向量中与开启位相对应的项,例如,如果bitarray[0]为1,则输出original[0],如果bitarray[1]为1,则输出输出original[1]

4)对这些位调用next_permutation()以获得“下一个”位模式。

重复步骤3和4,直到next_permutation()为false

所以基本上,你需要一些n个项目来开始并将最右边的r位初始化为1.然后你使用next_permutation来改变位模式。我建议你先在纸上做这件事,看看它是如何运作的。

以下是一个例子。它有3个项目的硬编码,所以请把它当作它的价值。

#include <vector>
#include <algorithm>
#include <string>
#include <iostream>

void OutputVector (const std::vector<std::string>& theVect, bool* bArray, int nItems)
{
    for (int i = 0; i < nItems; ++i)
       if (bArray[i] == true)
         std::cout << theVect[i] << " ";
    std::cout << "\n";
}

using namespace std;

int main()
{
    std::vector<std::string> original = { "Brown", "Yellow", "Blue" };
    bool myBits[3] = { false };  // everything is false now
    myBits[1] = myBits[2] = true;  // set rightmost bits to true
    do  // start combination generator
    {
       OutputVector(original, myBits, 3);
    } while (next_permutation(myBits, myBits + 3));  // change the bit pattern
}

举个例子:

我们从这个位模式开始(调用位数组bitArray): 011

这意味着我们输出original[1]original[2],因为bitArray[1]bitArray[2]是“true”(设置为1)。

在这些位上调用next_permutation时,位模式更改为: 101

我们输出original[0]original[2],因为bitArray[0]bitArray[2]为“true”。

调用

next_permutation,更改位数组: 110

输出

original[0]original[1]

如果再次调用,

next_permutation将返回false,因为没有更多的排列。

完成。

答案 2 :(得分:0)

我的解决方案,比使用std::next_permutation更快

#include "../combinations/combinations"
#include <iostream>
#include <string>
#include <vector>

int
main()
{
    std::vector<std::string> original(6);
    original[0] = "Brown";
    original[1] = "Yellow";
    original[2] = "Blue";
    original[3] = "Red";
    original[4] = "Green";
    original[5] = "Purple";
    for_each_combination(original.begin(), original.begin()+3, original.end(),
                         [](auto begin, auto end)
                         {
                              std::cout << "{";
                              bool print_comma = false;
                              for (; begin != end; ++begin)
                              {
                                   if (print_comma)
                                       std::cout << ", ";
                                   print_comma = true;
                                   std::cout << *begin;
                              }
                              std::cout << "}\n";
                              return false;
                         });
}

查找for_each_combination here

输出:

{Brown, Yellow, Blue}
{Brown, Yellow, Red}
{Brown, Yellow, Green}
{Brown, Yellow, Purple}
{Brown, Blue, Red}
{Brown, Blue, Green}
{Brown, Blue, Purple}
{Brown, Red, Green}
{Brown, Red, Purple}
{Brown, Green, Purple}
{Yellow, Blue, Red}
{Yellow, Blue, Green}
{Yellow, Blue, Purple}
{Yellow, Red, Green}
{Yellow, Red, Purple}
{Yellow, Green, Purple}
{Blue, Red, Green}
{Blue, Red, Purple}
{Blue, Green, Purple}
{Red, Green, Purple}

如果受限于C ++ 98,或者您只是喜欢命名函数,则可以执行以下操作:

#include "../combinations/combinations"
#include <iostream>
#include <string>
#include <vector>

bool
print(std::vector<std::string>::const_iterator begin,
      std::vector<std::string>::const_iterator end)
{
    std::cout << "{";
    bool print_comma = false;
    for (; begin != end; ++begin)
    {
        if (print_comma)
            std::cout << ", ";
        print_comma = true;
        std::cout << *begin;
    }
    std::cout << "}\n";
    return false;
}

int
main()
{
    std::vector<std::string> original(6);
    original[0] = "Brown";
    original[1] = "Yellow";
    original[2] = "Blue";
    original[3] = "Red";
    original[4] = "Green";
    original[5] = "Purple";
    for_each_combination(original.begin(), original.begin()+3, original.end(),
                         print);
}

源代码在boost软件许可下是开源的,但不是boost的一部分。随意使用。目的是该源代码可以免费使用,并鼓励免费使用。如果您的律师对此许可证不满意,请告诉我,我将尽力让他们感到高兴,免费。

相同的链接包括:

template <class BidirIter, class Function>
Function
for_each_permutation(BidirIter first,
                     BidirIter mid,
                     BidirIter last,
                     Function f);

template <class BidirIter, class Function>
Function
for_each_reversible_permutation(BidirIter first,
                                BidirIter mid,
                                BidirIter last,
                                Function f);

template <class BidirIter, class Function>
Function
for_each_circular_permutation(BidirIter first,
                              BidirIter mid,
                              BidirIter last,
                              Function f);

template <class BidirIter, class Function>
Function
for_each_reversible_circular_permutation(BidirIter first,
                                         BidirIter mid,
                                         BidirIter last,
                                         Function f);

template <class BidirIter, class Function>
Function
for_each_combination(BidirIter first,
                     BidirIter mid,
                     BidirIter last,
                     Function f);

代码