Leetcode轻松链接列表问题:为什么我的解决方案有误? (21.合并2个排序的列表)

时间:2020-09-02 01:58:53

标签: javascript algorithm linked-list

问题: 合并两个排序的链表,并将其作为新的排序表返回。应该通过将前两个列表的节点拼接在一起来创建新列表。

示例: 输入:1-> 2-> 4,1-> 3-> 4 输出:1-> 1-> 2-> 3-> 4-> 4

我的解决方案:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */

var mergeTwoLists = function(l1, l2, l3) {
    if (l2 === null) {
        l3.next = l1;
        return l3;
    }
    if (l1 === null) {
        l3.next = l2;
        return l3;
    }
    if (l2.val < l1.val) {
        if (l3) {
            l3.next = new ListNode(l2.val) 
        }
        else {
            l3 = new ListNode(l2.val)
        }
        return mergeTwoLists(l1, l2.next, l3)
    } else {
        if (l3) {
            l3.next = new ListNode(l1.val);
        }
        else {
            l3 = new ListNode(l1.val);
        }
        return mergeTwoLists(l1.next, l2, l3)
    }
};

我的输出仅为1-> 4,而不是1-> 1-> 2-> 3-> 4-> 4。谁能告诉我为什么?

3 个答案:

答案 0 :(得分:1)

您遇到的问题的主要原因是您的函数具有的第三个参数:这与挑战说明不符。没有第三个参数。您需要创建不带此值的返回列表。

我了解您已尝试将部分结果作为第三个参数传递,并希望在每次递归调用中扩展该部分结果,但随后出现了问题:

首先,在前两个if块中,您假设l3不为null,但是您不能确定是否为null。如果输入包含一个空列表,则您的代码将产生异常。

第二,如果l3代表具有多个元素的列表,则此代码将覆盖l3l3.next之间的现有链接,因此原始{{1} }(以及后面的所有节点)将会丢失。

尽管您可以解决此问题,但首先找到l3.next中的终止节点,还有更好的方法。这种更好的方法实际上是精心设计的递归的核心原则:

如果可能,请勿将部分结果传递给递归调用,以将部分结果扩展为最终结果。相反,尝试以这种方式制作函数,即它不需要来自调用者的任何部分结果,但可以对输入执行其工作,就好像这是非常原始的输入一样。调用者应使用返回的值将那个视为部分结果,并在将其返回给调用者之前对其进行扩展。

l3

答案 1 :(得分:0)

您可以使用Sentinel Node以便更轻松:

const mergeTwoLists = function(l1, l2) {
    const sentinel = {
        val: -1,
        next: null
    }

    let head = sentinel
    while (l1 && l2) {
        if (l1.val > l2.val) {
            head.next = l2
            l2 = l2.next
        } else {
            head.next = l1
            l1 = l1.next
        }
        
        head = head.next
    }

    head.next = l1 || l2

    return sentinel.next
}

如果您要递归执行,则不需要l3

const mergeTwoLists = function(l1, l2) {
    if (l1 === null) {
        return l2
    }

    if (l2 === null) {
        return l1
    }

    if (l1.val < l2.val) {
        l1.next = mergeTwoLists(l1.next, l2)
        return l1

    } else {
        l2.next = mergeTwoLists(l1, l2.next)
        return l2
    }
}

答案 2 :(得分:0)

您的答案仅返回1->4,因为您没有迭代新创建的合并列表,即l3。您直接在做l3.next=somevalue。由于l3是一个列表,因此您首先需要对其进行迭代,并将值或列表添加到其最后一个节点,其中l3.next将是null

这是应该为您提供理想结果的代码

function ListNode(val, next) {
  this.val = (val === undefined ? 0 : val)
  this.next = (next === undefined ? null : next)
}
var mergeTwoLists = function(l1, l2, l3) {
  let addToMergedList = (l3, val) => {
    let rootNode = l3
    while (l3.next !== null)
      l3 = l3.next;
    l3.next = new ListNode(val);
    return rootNode;
  }
  if (l2 === null) {
    let root = l3
    if(!root)
      return l1
    while (l3.next)
      l3 = l3.next;
    l3.next = l1;
    return root;
  }
  if (l1 === null) {
    let root = l3
    if(!root)
     return l2
    while (l3.next)
      l3 = l3.next;
    l3.next = l2;
    return root;
  }
  if (l2.val < l1.val) {
    if (l3) {
      l3 = addToMergedList(l3, l2.val)
    } else {
      l3 = new ListNode(l2.val)
    }
    return mergeTwoLists(l1, l2.next, l3)
  } else {
    if (l3) {
      l3 = addToMergedList(l3, l1.val)
    } else {
      l3 = new ListNode(l1.val);
    }
    return mergeTwoLists(l1.next, l2, l3)
  }
};

let l1={val:1,next:{val:2,next:{val:4,next:null}}}
let l2={val:1,next:{val:3,next:{val:4,next:null}}
console.log(mergeTwoLists(l1, l2))