【问题标题】:Solve all 2d string vector combinations without using recursion? (C++ )在不使用递归的情况下解决所有二维字符串向量组合? (C++)
【发布时间】:2018-04-13 06:21:33
【问题描述】:

问题是:

创建一个函数来计算字符串数组的所有组合,例如:{ { "red", "wooden", "gate" }, { "lazy", "little", "man" }, { "what", "where", "who", "why" } } 以输出:red lazy what、red lazy where、red lazy who、red lazy why、red little what 等... ..

此函数将打印第一个数组中的一个单词、第二个数组中的一个单词、第三个数组中的一个单词等的所有组合。

您的解决方案可能不使用递归

注意:数组的数量和每个数组中的元素数量可能会有所不同!您的方法需要能够处理此问题。


我正在尝试练习我的算法,而这个问题简直让我发疯。我试过集思广益一些事情,但在这一点上,花了几个小时无处可去。当我想到也许我只需要创建一个字符串向量(尽管这将成为一个非常大的向量......现在,让我们称之为矢量endings)。如果我在给定vector<vector<string>> 的外部向量中向后遍历并通过将每个结尾附加到当前外部向量中的每个字符串来更新endings,那么当我到达第一个外部向量时,我的所有组合将是在endings.

我可能没有立即想到这一点,因为我认为如果我只是打印,我不应该存储这么多。无论如何,这里有一些拙劣的代码,我停止工作以发布此内容。不多。

vector<vector<string>> ar = {{"red", "wooden", "gate"}, 
                             {"lazy", "little", "man"}, 
                             {"what", "where", "who", "why"}};

vector<string> res(ar.size());

for (int i = 0; i < ar.size(); i++) {   
    res[i]= ar[i][0];
}

int i;

for (i = ar.size()-1; i > 0; i--) {
    for (int j = arr.size()-1-i, j > arr.size()-1-i; j--) {
                // ...
    }
}

让我知道你建议如何解决这个问题。

【问题讨论】:

  • 提示:您可以使用堆栈将任何递归转换为迭代
  • 看std::next_permuatation的源码
  • @RichardHodges 这与排列无关。
  • 假设你所有的字符串数组都有相同的内容,{"0","1"}。假设有四个。你期望什么样的输出?如果它们都包含{"0","1","2"} 怎么办? (现在是关键部分)如果一些包含{"0","1"} 而另一些包含{"0","1","2"},你能应付吗?
  • 嗨,也许这篇 SO 文章可以帮助你stackoverflow.com/questions/18732974/…

标签: c++ arrays string recursion vector


【解决方案1】:

“计算机科学中的所有问题都可以通过另一个层次的间接性来解决”- David Wheeler

https://en.wikipedia.org/wiki/Indirection

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

void print(std::vector<std::vector<std::string>> const& astrs, std::vector<std::size_t> const& idxs)
{
    const char* sep = "";
    for(std::size_t i = 0 ; i < astrs.size() ; ++i)
    {
        std::cout << sep << astrs[i][idxs[i]];
        sep = ", ";
    }
    std::cout << '\n';
}

bool next_in_sequence(std::vector<std::vector<std::string>> const& astrs, std::vector<std::size_t>& idxs)
{
    for(std::size_t i = astrs.size() ; i-- ; )
    {
        if(++idxs[i] != astrs[i].size())
        {
            return true;
        }
        idxs[i] = 0;
    }

    return false;
}

int main()
{
    std::vector<std::vector<std::string>> const ar = {
        {"red", "wooden", "gate"}, 
        {"lazy", "little", "man"}, 
        {"what", "where", "who", "why"}
    };

    vector<std::size_t> idxs(ar.size(), 0);

    do
    {
        print(ar, idxs);
    }
    while(next_in_sequence(ar, idxs));
}

此解决方案构建了一系列不雅点。将此数组视为一个整数,其中每个数字列都有自己的基数。基数是ar + 1 中相应“槽”中的字符串数。

我们需要做的就是“增加”“整数”直到它换行。这是在函数next_in_sequence() 中执行的。

这是表达这个想法的另一种方式。它在概念上效率较低(实际上,可能不适用于“小”输入集),但以另一种方式展示了这个想法 - 计算组合的最大数量,遍历每个组合并计算我们的多基索引的“数字”我们去的代表。它不需要额外的存储空间,但代价是重复计算:

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

std::size_t combinations_at(std::vector<std::vector<std::string>> const& astrs, std::size_t col)
{
    std::size_t result = 1;
    while (col != astrs.size())
    {
        result *= astrs[col].size();
        ++col;
    }
    return result;
}

void print(std::vector<std::vector<std::string>> const& astrs, std::size_t which)
{
    const char* sep = "";
    for(std::size_t col = 0 ; col != astrs.size() ; ++col)
    {
        auto nextmod = combinations_at(astrs, col + 1);
        auto i = which / nextmod;
        which %= nextmod;
        std::cout << sep << astrs[col][i];
        sep = ", ";
    }
    std::cout << '\n';
}

int main()
{
    std::vector<std::vector<std::string>> const ar = {
        {"red", "wooden", "gate"},
        {"lazy", "little", "man"},
        {"what", "where", "who", "why"}
    };

    const auto limit = combinations_at(ar, 0);
    for(std::size_t i = 0 ; i < limit ; ++i)
        print(ar, i);
}

【讨论】:

  • 您能否将您的函数重命名为combination,因为这真的不是一个排列(或者我可能遗漏了一些东西)。也显示输出会很好。
  • @YesThatIsMyName 我也不认为这是一个组合。已重命名为next_in_sequence
  • @RichardHodges 所以我度过了一个非常忙碌的一周,终于有机会在纸上完成这个/真正分析每次迭代期间发生的事情......(有趣的是这样的事情凌晨 3 点如此可怕,然后第二天就搁置了)。无论如何-这非常酷,我对解决方案的真正“简单”印象深刻。谢谢你的分享和解释。很棒的思维方式。
  • @Bella 很高兴能提供帮助。
猜你喜欢
  • 2014-09-29
  • 2020-08-04
  • 2011-09-05
  • 2019-03-18
  • 2019-01-02
  • 2013-04-08
  • 2011-10-20
  • 1970-01-01
相关资源
最近更新 更多