假设有n个级别,并且在每个级别中,您可以从两个可能的字符中选择一个,打印所有可能的字符串
如: -
假设我们有3个级别: -
level1: - a b
level2: - c d
level3: - e f
可能的字符串是: -
王牌
2. acf
ade
adf
5. bce
6. bcf
7. bde
8. bdf
我知道样本空间是2 ^ n所以所需的时间是O(2 ^ n),但我无法弄清楚如何编写它。 有什么可能的方法和我必须阅读哪些主题来解决这些问题?
答案 0 :(得分:5)
选择两个选项可以轻松实现。把它归为一点。像这样:
char buf[3];
for(unsigned i = 0; i < 10; ++i)
{
buf[0] = i & 4 ? 'b' : 'a';
buf[1] = i & 2 ? 'd' : 'c';
buf[2] = i & 1 ? 'f' : 'e';
std::string str = std::string(buf, 3);
}
答案 1 :(得分:2)
在我看来,递归是不正确答案。
你所拥有的本质上是一个三位二进制数字,其中0和1以外的字符代表数字。
生成所有组合包括简单地计算所有数字到极限,然后使用这些位来选择正确的字符。
这也可以概括。例如,如果您在每个级别有五个级别和六个选项,那么您将查看基础6中的5位数字(然后是每个数字可以表示的字符的2D集合)。
就个人而言,我认为我不会使用long if / then / else(或等效的三元运算符)。如上所述,我使用2D集合,只是索引到该集合:
char const *names [] = { "ab", "cd", "ef" };
for (unsigned i = 0; i < 8; i++)
std::cout << names[0][i >> 0 & 1]
<< names[1][i >> 1 & 1]
<< names[2][i >> 2 & 1]
<< "\n";
虽然条件运算符(几乎不可用)可用于这个微不足道的案例,但对于任何较大版本的问题(例如,5位数,基数为6的版本),它们很快变得难以处理。
答案 2 :(得分:1)
您似乎正在寻找的明显(并且无可否认的丑陋)方法使用三个嵌套循环:
char level1[] = "ab";
char level2[] = "cd";
char level3[] = "ef";
int x, y, z;
for (x = 0; x < 2; ++x)
{
for (y = 0; y < 2; ++y)
{
for (z = 0; z < 2; ++z)
{
printf("%c%c%c\n", level1[x], level2[y], level3[z]);
}
}
}
答案 3 :(得分:0)
具有任意数量级别的平凡算法(也会执行大量复制字符串):
class StringCombinations {
public:
// filled somehow
std::vector<std::pair<char, char> > choices;
void printStrings(size_t level, std::string prefix) {
assert(level < choices.size());
if (level == choices.size() - 1) {
cout << prefix << choices[i].first();
cout << prefix << choices[i].second();
} else {
printStrings(level +1, prefix + choices[i].first());
printStrings(level +1, prefix + choices[i].second());
}
}
}
这样叫:
StringCombinations sc;
// Set the choices table somehow.
...
sc.printStrings(0, "");
当然,选择表也可以是另一个作为const-reference传递的方法参数,如果你有一个静态方法更方便的话。
-
一个更好的选择(只是针对3个级别提出的n级回答的概括),而没有复制递归调用(尽管不太容易理解):
请注意,如果您不直接打印,则可以使用cout <<
重新mystring +=
。
// all strings have size 2, 0'th char and 1'st char correspond to the choices
std::vector<std::string> choices;
void printStrings() {
for (size_t i = 0; i < static_cast<size_t>(pow(2, choices.size())); ++i) {
for (size_t j = 0; j < choices.size(); ++j) {
// Checks the bit in i (from the right) that fits the current level (j).
cout << choices[j][i & (j << x)];
// 2^#levels different values of i, ensure as many different outcomes
// (disregarding trivial choices between, e.g., 'a' and 'a'
}
}
}
答案 4 :(得分:0)
您可以将int从1迭代到pow(2,n)并查看每个索引的二进制表示。如果该位为0则使用左侧,如果该位为1则使用右侧:
void PrintDigits(char **str, int size, int val)
{
char *tmp = new char[size + 1];
assert(tmp);
tmp[size] = '\0';
while (size) {
tmp[size - 1] = str[size - 1][val % 2];
val = val >> 1;
size --;
}
printf("%s\n", tmp);
}
int main(int argc, char *argv[])
{
char *str[] = {"ab", "cd", "ef", "gh"};
int len = sizeof(str) / sizeof(str[0]);
for (int i = 0; i < (1 << len); i++) {
PrintDigits(str, len, i);
}
return 0;
}
输出:
aceg
aceh
acfg
acfh
adeg
adeh
adfg
adfh
bceg
bceh
bcfg
bcfh
bdeg
bdeh
bdfg
bdfh