【问题标题】:String Reversal Memory Consumption Differences字符串反转内存消耗差异
【发布时间】: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


【解决方案1】:

substr() 每次都会返回一个 new 字符串,并包含与之相关的所有内存使用情况。因此,如果您要对substr() 进行N-1 调用,那是您无缘无故使用的O(N^2) 额外内存。

不过,使用std::string,您可以就地修改它,只需使用简单的for 循环对其进行迭代。或者只是使用std::reverse:

void reverseString(string &s) {
    std::reverse(s.begin(), s.end());
}

无论哪种方式(for 循环或算法)都需要O(1) 额外的内存 - 它实际上只是一系列swaps,所以你只需要一个额外的char 作为临时的。好多了。

【讨论】:

  • 谢谢,是的,你能得到的最好的解决方案是迭代交换必要的字符,我只是好奇递归实现的确切内存消耗,我猜是为了理论上的缘故
  • @DomFarolino 与您迭代执行的方式相同...交换一对chars,然后以更严格的界限调用。
猜你喜欢
  • 1970-01-01
  • 2015-07-04
  • 2015-02-21
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
  • 2017-10-30
相关资源
最近更新 更多