我使用位掩码生成字符串的所有排列。
void recurse(string s, int mask,int taken){
if(taken == n){
cout << " ";
return;
}
for(int i = 0; i < n; i++){
if(((1 << i) & mask) == 0){
cout << s[i];
recurse(s, (mask|(1 << i)), taken + 1);
}
}
}
在此函数中,n是字符串的长度。我用跟踪变量跟踪到目前为止打印了多少个字符。 在我正在调用的主函数中
recurse(s,0,0);
但这不能正常工作。 输入
红色
它的输出是
红 德 ERD 博士 DRE ER
我哪里错了?
更新 //下面的代码工作正常。
void recurse(string s, int mask,int taken, string pref){
if(taken == n){
cout << pref <<endl;
return;
}
for(int i = 0; i < n; i++){
if(((mask >> i) & 1) == 0){
recurse(s,(mask | (1 << i)),taken + 1, pref + s[i]);
}
}
}
答案 0 :(得分:2)
实际上,提问者自己提供了答案。 (祝贺。)
由于我已经开始摆弄(无法抗拒),我也想提出我的解决方案:
#include <iostream>
#include <string>
using namespace std;
void recurse(
const string &s, unsigned mask = 0, const string &out = string())
{
size_t n = s.size();
if (out.size() == n) cout << ' ' << out;
for (size_t i = 0; i < n; ++i) {
unsigned bit = 1 << i;
if (mask & bit) continue;
recurse(s, mask | bit, out + s[i]);
}
}
int main()
{
string test = "red";
recurse(test);
cout << endl;
return 0;
}
编译并测试:
red rde erd edr dre der
recurse()
遍历s
的所有字符,查找尚未在mask
中标记的字符。每个找到的字符都会添加到输出out
。然后,递归调用会为所有未被捕获的字符重复它。
自己在ideone上查看示例代码。
答案 1 :(得分:0)
您的第一个代码是访问此树的每个节点一次并打印一个字符。所以它提供了错误的输出。
另一方面,您使用了一些冗余变量。
而不是n
,您应该使用s.size()
。
在第二个代码而不是taken
中,您应该使用pref.size()
。
答案 2 :(得分:0)
这是另一个版本。它与发问者的代码有两种不同:
可以省略参数def join_paths(base_path, relative_paths):
# Taking care of first case where base_path is "/" root
if base_path == "/":
return relative_paths
# Convert the base_path to a list by splitting at "/" ["", "folder1", "folder2"]
base_path_list = base_path.split("/")
# Convert the relative_paths to a list by splitting at "/" ["", "folder1", "folder2"]
relative_paths_list = relative_paths.split("/")
# Take difference between length of base_path_list and length of relative_paths_list
len_diff = len(relative_paths_list) - len(base_path_list)
# Validate if difference in length is greater than 0 else it wont find
# the sub list it needs to append
if len_diff > 0:
# Get last 'n' elements from relative_paths_list where n is len_diff
list_to_append = relative_paths_list[-len_diff:]
# Join the base path list with sub-list we just created above
final_list = base_path_list + list_to_append
# Join the elements in list with "/"
return "/".join(final_list)
elif len_diff == 0:
final_list = base_path_list
return "/".join(final_list)
else:
print("SOmething is really wrong")
# run the code
print(join_paths("/Windows/kin_test/path2", "/Windows/kin_dev/path2/path3"))
,而可以使用taken
。它基本上检查mask + 1 == (1 << n)
的{{1}}至1
的位是否全部为1。如果是这样,则递归深度为n-1
,我们将打印排列。
如果字符串的大小很大,则在每次迭代中复制mask
可能会很慢。我们可以改为使用参考。
n
其中string pref
是字符串的大小。输出是
#include <iostream>
#include <string>
using namespace std;
void recurse(string s, int mask, string &pref);
int n = 3;
int main()
{
string pref("");
recurse(string("abc"), 0, pref);
return 0;
}
void recurse(string s, int mask, string &pref)
{
if (mask + 1 == (1 << n)) {
cout << pref << endl;
return;
}
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 0) {
pref += s[i];
recurse(s, (mask | (1 << i)), pref);
pref.erase(pref.end() - 1);
}
}
}