用 JavaScript 完成链表操纵 - 18 Recursive Reverse

TL;DR

用递归的体式格局反转链表,系列目次见 前言和目次

需求

完成函数 reverse() 用递归的体式格局反转链表。例子以下:

var list = 2 -> 1 -> 3 -> 6 -> 5 -> null
reverse(list) === 5 -> 6 -> 3 -> 1 -> 2 -> null

解法

让我们先思索一下递归的也许解法:

function reverse(head) {
  const node = new Node(head.data)
  const rest = reverse(head.next)
  // 把 node 放到 rest 的末端,并返回 rest
}

贫苦的处所就在末了,把节点到场链表的末端须要起首遍历全部链表,这无疑异常低效。我们在上一个 kata 的轮回里是怎样处理的呢?保护一个 result 变量代表反转链表,然后每次把新节点放到 result 的头部,同时把新节点当作新的 result ,也许这个模样:

let result
for (let node = list; node; node = node.next) {
  result = new Node(node.data, result)
}

为了在递归里到达一样的结果,我们也必需保护这么一个变量。为了在每次递归过程当中都能用到这个变量,我们得把它当函数的参数通报下去,reverse 的函数署名就变成如许:

function reverse(head, acc) { ... }

这里 acc 就是反转的链表。整顿一番后的代码以下:

function reverse(head, acc = null) {
  return head ? reverse(head.next, new Node(head.data, acc)) : acc
}

上面这段代码同时也是尾递归。在递归函数中开分外的参数非常罕见的做法,也是尾递归优化的必要手腕。

参考资料

Codewars Kata
GitHub 的代码完成
GitHub 的测试

    原文作者:darkbaby123
    原文地址: https://segmentfault.com/a/1190000008485170
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞