以下是打印给定字符串的所有排列的代码。代码编译但不打印任何内容。
using namespace std;
void RecPermute(string, string);
int main() {
RecPermute("", "abc");
return 0;
}
void RecPermute(string soFar, string rest) {
if (rest == " ") {
cout << soFar << endl;
} else {
for(int i=0; i<rest.length(); i++) {
string next = soFar + rest[i];
string remaining = rest.substr(0, i) + rest.substr(i+1);
RecPermute(next, remaining);
}
}
}
需要修复什么?
答案 0 :(得分:13)
您的方法有效(使用greedybuddha提供的正确条件),但可以更简单地实现(如Chris所建议的那样)。
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::string s("abcdefg");
do
{
std::cout << s << "\n";
}
while ( std::next_permutation(s.begin(), s.end()) );
}
那它做了什么? std::next_permutation
需要两个迭代器,一个是字符串的开头,第二个是结尾,所以基本上你说的是“考虑整个字符串”。它会置换字符串s
,以便在调用之后,s
包含将在s
的上一个值之后直接出现在词典顺序中的唯一排列。如果s
是最后一个这样的排列(即输入“abcdefg”的“gfedcba”),std::next_permutation
会返回false
,因此您知道自己已完成。
由于您没有使用此代码创建任何新的(临时)字符串,因此它不仅更具可读性,而且更快。在我的机器上,对于“abcdefghij”,您的算法大约需要5秒钟,使用std::next_permutation
的算法在不到一秒的时间内完成。对于另一个角色,它变得更糟,到54秒对6.8秒。
请注意,如果初始字符串未排序,则不将提供完整的排列列表。但当然有一个简单的解决方案:在置换之前执行std::sort(s.begin(), s.end());
。
答案 1 :(得分:1)
所以你真是太诱人了。您只需要匹配空字符串而不是空格。您可以通过匹配空字符串""
来完成此操作。
更改
if (rest == " ") { ... }
到
if (rest == "") { ... }
你忘了rest.substr(i + 1)的长度,它应该是(i + 1,i-3);