C++ 在C+中用递归替换循环的N级+;

C++ 在C+中用递归替换循环的N级+;,c++,for-loop,recursion,tail-recursion,C++,For Loop,Recursion,Tail Recursion,一段时间以来,我一直在努力想出一种方法来计算所有字符串的各种组合。不过,与web上的大多数组合方法不同,该算法必须生成每个组合,包括所有组合元素不在单个组合中的组合。也就是说,如果我将“Hello”、“New”和“World”组合在一起,我要寻找的组合是: HelloNewWorld HelloNew HelloWorld Hello NewWorld New World 我大学的一位教授确实提出了一个快速而肮脏的解决方案,但它使用嵌套for循环 #include <iostream&g

一段时间以来,我一直在努力想出一种方法来计算所有字符串的各种组合。不过,与web上的大多数组合方法不同,该算法必须生成每个组合,包括所有组合元素不在单个组合中的组合。也就是说,如果我将“Hello”、“New”和“World”组合在一起,我要寻找的组合是:

HelloNewWorld
HelloNew
HelloWorld
Hello
NewWorld
New
World
我大学的一位教授确实提出了一个快速而肮脏的解决方案,但它使用嵌套for循环

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

int main()
{
std::vector<std::array<std::string, 2>> vec(3);
vec[0] = {"Hello", ""};
vec[1] = {"New", ""};
vec[2] = {"World", ""};
for (int i = 0; i < 2; i++)
    for (int j = 0; j < 2; j++)
        for (int k = 0; k < 2; k++)
            std::cout << vec[0][i] + vec[1][j] + vec[2][k] << std::endl;
}
#包括
#包括
#包括
#包括
int main()
{
std::vec(3);
vec[0]={“你好”,“你好”};
vec[1]={“新的”,即“};
vec[2]={“世界”,即“};
对于(int i=0;i<2;i++)
对于(int j=0;j<2;j++)
对于(int k=0;k<2;k++)

std::cout如果唯一的可能性是一个单词出现或不出现,那么就有两种可能性。因此,对于n个单词,您有2^n个组合。因此,您只需通过从0(包括)到2^n-1(包括)的2^n数字进行计数,并将每个位映射到一个单词


无需递归,循环只需一次计数。

如果唯一的可能性是一个单词出现或不出现,则有两种可能性。因此,对于n个单词,您有2^n个组合。因此,您只需通过从0(包括)到2^n-1(包括)的2^n数字进行计数,并将每个位映射到一个单词


无需递归,循环只需一次计数。

如果我理解正确,您希望生成字符串的所有组合。在这种情况下,您可以使用BFS以及集合和队列来生成组合,我将尝试解释

假设您的字符串是
ABCD
。您现在有一个要添加的队列
ABCD
和一个要添加的集合
ABCD

while the queue is not empty
1) you pop the top element
2) you generate substrings of that popped element
  a) if that substring is not in the set add it to the queue
要在步骤2中生成子字符串,请执行以下操作

for(int i =0;i<string.length();i++)
{
  string substr1 = string.substr(0,i);
  string substr2 = string.substr(i,string.length()-1);
  string substring = substr1+substr2;
}

for(int i=0;i如果我理解正确,您希望生成字符串的所有组合。在这种情况下,您可以使用BFS以及集合和队列来生成组合,我将尝试解释

假设您的字符串是
ABCD
。您现在有一个要添加的队列
ABCD
和一个要添加的集合
ABCD

while the queue is not empty
1) you pop the top element
2) you generate substrings of that popped element
  a) if that substring is not in the set add it to the queue
要在步骤2中生成子字符串,请执行以下操作

for(int i =0;i<string.length();i++)
{
  string substr1 = string.substr(0,i);
  string substr2 = string.substr(i,string.length()-1);
  string substring = substr1+substr2;
}

用于(int i=0;i对于N个元素的向量,通过使用从
k=1
k=N
的所有组合,可以非常有效地实现这一点。使用可用的Howard Hinnant库,可以相当有效地使用它。在我的例子中,我将库命名为
sampling.h
,它是唯一的外部依赖项,可以在它的疲倦

这正是你的帖子所描述的。因为lambda是一个自定义的函子,可以存储状态,所以你可以对这些组合做任何你想做的事情:存储一个副本,打印它们,等等


这比在标准库中无需大量工作或从标准库的建议中获得的任何东西都要快得多。例如,
std::next_composition
std::next_permutation
(前者未包括在内,但建议使用)。我强烈建议阅读Howard Hinnant的完整博客文章:这很有启发性。他的实现的时间复杂性和速度比大多数其他建议都要快。如果您需要高性能组合或置换,他已经为您完成了这项工作。

使用
k中的所有组合,您可以非常高效地完成这项工作=1
k=N
表示N个元素的向量。使用可用的Howard Hinnant库,您可以相当有效地使用它。在我的例子中,我将库命名为
sampling.h
,它是唯一的外部依赖项,可以完整地查看

这正是你的帖子所描述的。因为lambda是一个自定义的函子,可以存储状态,所以你可以对这些组合做任何你想做的事情:存储一个副本,打印它们,等等


这比在标准库中无需大量工作或从标准库的建议中获得的任何东西都要快得多。例如,
std::next_composition
std::next_permutation
(前者未包括在内,但建议使用)。我强烈建议阅读Howard Hinnant的完整博文:这很有启发性。他的实现的时间复杂性和速度比大多数其他建议都要快。如果你需要高性能的组合或排列,他已经为你完成了这项工作。

在每个级别上,无论是否使用当前的文字打印,它都会重复出现当它到达所有单词的末尾时的结果:

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

void recurse(std::vector<std::string> &values,size_t level,std::string str) {
  if (level<values.size()) {
    recurse(values,level+1,str+values[level]);
    recurse(values,level+1,str);
  } else {
    std::cout<<str<<"\n";
  }
}

int main(int argc, char*argv[]) {
  if (argc<2)
    std::cout<<argv[0]<<" <word> [<word> [...]]\n";
  else {
    std::vector<std::string> values;
    for(int i=1;i<argc;++i) {
      values.push_back(argv[i]);
    }
    recurse(values,0,"");
  }
  return 0;
}

在每个级别上,它都会在有当前单词和没有当前单词的情况下递归,当它到达所有单词的末尾时,会打印结果:

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

void recurse(std::vector<std::string> &values,size_t level,std::string str) {
  if (level<values.size()) {
    recurse(values,level+1,str+values[level]);
    recurse(values,level+1,str);
  } else {
    std::cout<<str<<"\n";
  }
}

int main(int argc, char*argv[]) {
  if (argc<2)
    std::cout<<argv[0]<<" <word> [<word> [...]]\n";
  else {
    std::vector<std::string> values;
    for(int i=1;i<argc;++i) {
      values.push_back(argv[i]);
    }
    recurse(values,0,"");
  }
  return 0;
}

是一个要求,他们必须是文字,或严格的字符组合?我强烈建议您使用Howard Hinnant的工作,创造高效的组合库在C++中。它们是递归的,但它们是快速,便携,易于使用。在这种情况下,使用<代码> STD::String S =“AB”;(size_t i=0;i@M4rc要求它们必须是文字。很抱歉,我应该在我的帖子中这么说。如果你需要一个真正的N级for循环(笛卡尔积)披露:我写了这个:@AlexanderHuszagh Howard Hinnat的组合库看起来很有趣,你的代码看起来很好,但它们都不能提供我想要的输出。这两个选项都不能提供组合元素的组合,这些组合元素在某些组合中不存在这是我知道如何描述它的最好方法。我编辑了我的文章,希望能澄清我所寻找的。是他们必须是单词的要求之一,还是严格的字符组合?我强烈建议你用Howard Hinnant的工作来在C++中创建高效的组合库。它们是递归的,但它们是。