【问题标题】:javscript recursion string reversejavascript递归字符串反向
【发布时间】:2020-08-09 06:20:37
【问题描述】:

我试图自己找到一个递归解决方案来反转字符串 s,但它为 >1 字符的字符串返回“未定义”。 有人可以帮我调试吗? 我知道这不是优雅的方式,但发现错误可以帮助我进步。

非常感谢你!

var revFunc = function (s, r, n, i) {
  if (i > n) {
    return r;
  }

  r = r + s[n - i];
  i++;
  revFunc(s, r, n, i);
};

var reverse = function (s) {
  var r = "";
  var n = s.length - 1;
  var i = 0;
  if (n < 1) {
    return s;
  }
  return revFunc(s, r, n, i);
};

【问题讨论】:

  • 首先,注意你的缩进。它将使您的代码更易于管理和阅读 - 对您和我们来说都是如此。
  • 在再次调用该函数之前,您需要一个返回语句。 return revFunc(s, r, n, i);

标签: javascript string recursion


【解决方案1】:

不适合递归

虽然已经提出的小修正修复了您的功能,但我想建议这个版本显示出对递归的误解。

您的函数正在使用递归来更新 while 循环中的局部变量。可以这样改写:

var reverse = function (s) {
  var r = "";
  var n = s.length - 1;
  var i = 0;
  if (n < 1) {
    return s;
  }
  while (i <= n) {
    r = r + s[n - i]
    i++
  }
  return r
};

console .log (reverse ('abcde'))

您使用的递归只是编写相同代码的另一种方式。

递归意味着一些不同的东西。我们希望我们的算法匹配我们的数据结构。为了使递归真正有意义,我们应该在递归数据结构上使用它。

但我们可以解决这个问题。

递归地思考一个字符串

通常有许多不同的方式来考虑单个数据结构。我们可以这样认为字符串是一个递归结构:

一个字符串要么是

  • 空字符串“”或
  • 一个字符后跟一个字符串

我们可以将非空字符串的两个部分称为headtail

在递归算法中使用递归定义

通过这个公式,我们可以编写一个匹配结构的递归算法:

字符串的反转要么是

  • 空字符串的反转(仍然是空字符串),或者
  • 尾部反转,然后是头部

然后代码实际上是自己编写的:

const reverse = (string) =>
  string .length == 0
    ? ""
    : reverse (string .slice (1)) + string[0]
    
console .log (reverse ('abcdefg'))

变体

这当然有可能的变化。当尾调用优化最终在 JS 环境中普遍存在时,我们可能希望做好准备,并且可以将其更改为尾递归版本,例如

const reverse = (string, result = "") =>
  string .length == 0
    ? result
    : reverse (string .slice (1), string [0] + result)

(请注意,此样式存在潜在问题。默认参数可能会妨碍在某些上下文中使用该函数。例如,您无法使用此版本成功调用 strings .map (reverse)。您可以通过以下方式执行此操作把它分成一个辅助函数和一个主函数,但这把我们带到了一个领域。)

或者,利用字符串是可迭代的事实,我们可以使用参数解构和默认值编写一个非常简单的版本:

const reverse = ([head = undefined, ...tail]) =>
  head == undefined
    ? ""
    : reverse (tail) + head

递归的优点

很难想象会比这简单得多。这个版本非常直接地捕获了算法。该算法与我们对数据结构的描述完全相关。

请注意这些函数都不使用的一件事:局部变量。简单递归通常可以以不需要它们的方式编写。这是一个重大的祝福,因为这意味着可变状态无处可藏。而可变状态是很多很多编程错误的根源。

【讨论】:

    【解决方案2】:

    你忘了return

    return revFunc(s, r, n, i);

    更新:

    var revFunc = function (s, r, n, i) {
      if (i > n) {
        return r;
      }
      r = r + s[n - i];
      i++;
      return revFunc(s, r, n, i);
    };
    

    建议:请为变量使用更好的名称,这很糟糕s,r,n,i

    【讨论】:

      【解决方案3】:

      你能尝试一个简单的解决方案吗:

      let str = "hello";
      let reverse_str = str.split("").reverse().join("");
      

      【讨论】:

      • “我试图自己找到一个递归解决方案来反转一个字符串。”这看起来更像是一种学习练习,而不是试图找到最好的逆转技术。
      猜你喜欢
      • 2014-07-10
      • 1970-01-01
      • 2014-02-22
      • 2013-05-11
      • 2020-12-21
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      相关资源
      最近更新 更多