用 JavaScript 完成链表操纵 - 14 Sorted Merge

TL;DR

把两个升序分列的链表兼并成一个,系列目次见 前言和目次

需求

完成函数 sortedMerge() 把两个升序分列的链表兼并成一个新链表,新链表也必需是升序分列的。这个函数应当对每一个输入的链表都只遍历一次。

var first = 2 -> 4 -> 6 -> 7 -> null
var second = 1 -> 3 -> 5 -> 6 -> 8 -> null
sortedMerge(first, second) === 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 6 -> 7 -> 8 -> null

有一些边境状况要斟酌:firstsecond 能够为 null ,在兼并过程当中 firstsecond 的数据有能够先取完。假如一个链表为空,就返回另一个链表(纵然它也为空),不需要抛出非常。

在做这个 kata 之前,发起先完成 Shuffle Merge

递归解法

代码以下:

function sortedMerge(first, second) {
  if (!first || !second) return first || second

  if (first.data <= second.data) {
    return new Node(first.data, sortedMerge(first.next, second))
  } else {
    return new Node(second.data, sortedMerge(first, second.next))
  }
}

跟上个 kata 相似的思绪。不过为了保证末了的效果是升序分列的,我们要取两个链表中值更小的首节点,添加到效果链表的末端。思绪就不赘述了 。

轮回解法

轮回是这个 kata 有意思的一点,许多边境状况的推断也发作在这里。很轻易写出如许的 if/else

let [p1, p2] = [first, second]
while (p1 || p2) {
  if (p1 && p2) {
    if (p1.data <= p2.data) {
      // append p1 data to result
    } else {
      // append p2 data to result
    }
  } else if (p1) {
    // append p1 to result
  } else {
    // append p2 to result
  }
}

上面例子里 p1p2 是指向两个链表节点的指针,在轮回中它们随时能够变成空,因而要比较数据大小起首就要推断两个都不为空。而且解释中的 append 代码也会有肯定反复。

为了处理这个题目,我们能够上个 kata 里换取指针的要领。完全代码以下:

function sortedMergeV2(first, second) {
  const result = new Node()
  let [pr, p1, p2] = [result, first, second]

  while (p1 || p2) {
    // if either list is null, append the other one to the result list
    if (!p1 || !p2) {
      pr.next = (p1 || p2)
      break
    }

    if (p1.data <= p2.data) {
      pr = pr.next = new Node(p1.data)
      p1 = p1.next
    } else {
      // switch 2 lists to make sure it's always p1 <= p2
      [p1, p2] = [p2, p1]
    }
  }

  return result.next
}

第 7 行推断 p1p2 为空,而且把非空的链表直接添加到 result 末端,省去了继承轮回每一个节点。第 17 行的指针换取让 p1 一直小于即是 p2 ,从而避免了反复的 append 代码 。其他技能如 dummy node 在之前的 kata 都有讲,就不多说了。

参考资料

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

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