查找字符串向量的 r 组合

Finding r-Combinations of a Vector of Strings

本文关键字:组合 向量 字符串 查找      更新时间:2023-10-16

我正在尝试生成给定字符串列表的所有可能的 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路线,但这给了我重复(我正在寻找组合,而不是排列......所以在上面的例子中,集合(黄色、蓝色(之后,(蓝色、黄色(不应该包括在内(。

您可以使用如下所示的内容:

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()));
}

现场示例

请尝试以下步骤:

1( 创建一系列 3 位。

2( 由于r是 2,将最右边的两个位初始化为 1。

3(输出向量中与on位对应的项,例如,如果bitarray[0]为1,则输出original[0],如果bitarray[1]为1,则输出original[1]等。

4( 调用位上的next_permutation()以获取"下一个"位模式。

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

所以基本上,你需要一个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]是"真实的"。

调用next_permutation,位数组更改: 110

输出original[0]original[1]

如果再次调用,next_permutation将返回 false,因为没有更多的排列。

做。

我的解决方案,比使用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

输出:

{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);

而且代码很快