【发布时间】:2016-06-20 07:59:36
【问题描述】:
假设我实现了以下两种字符串反转算法:
void reverse(string &s) {
if(s.size() == 1) return;
string restOfS = s.substr(1);
reverse(restOfS);
s = restOfS + s.at(0);
}
string reverseString(string s) {
if(s.size() == 1) return s;
return reverseString(s.substr(1)) + s.at(0);
}
int main() {
string name = "Dominic Farolino";
reverse(name);
cout << name << endl;
name = reverseString(name);
cout << name << endl;
return 0;
}
其中一个显然会修改给它的字符串,而其中一个会返回一个新字符串。由于第一个修改了给定的字符串并使用引用参数作为其与下一个递归堆栈帧的通信模式,我起初认为这会更有效,因为使用引用参数可以帮助我们不重复内存中的内容,但是我不相信是这样的。显然我们必须在这个void 函数中使用引用参数,但似乎我们正在撤消使用引用参数可能给我们带来的任何内存效率,因为我们每次都只是在堆栈上声明一个新变量。
简而言之,似乎第一个在每次调用时都复制引用,而第二个在每次调用时都复制值并仅返回其结果,从而使它们的内存消耗相等。
为了使第一个更高效,我觉得你必须这样做:
void reverse(string &s) {
if(s.size() == 1) return;
reverse(s.substr(1));
s = s.substr(1) + s.at(0);
}
但是编译器不允许我这样做:
error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}' from an rvalue of type 'std::basic_string<char>'
6:6: note: in passing argument 1 of 'void reverse(std::string&)'
这个分析正确吗?
【问题讨论】:
-
这不是C。请删除标签。
-
substr返回一个副本 - 这些方法中的每一个实际上都具有相同的内存要求。 -
@OliverCharlesworth 好的,谢谢,这意味着第一行的最后一行不能是 (
s = s.substr(1) + s.at(0);),因为原来的s保持不变? -
这是不可能的,但出于不同的原因 - 您需要 O(n) 递归调用,因此调用堆栈需要 O(n) 内存。
-
为什么不使用迭代器而不是子字符串? ideone.com/xQIJMM
标签: c++ string recursion space-complexity