问题: 合并两个排序的链表,并将其作为新的排序表返回。应该通过将前两个列表的节点拼接在一起来创建新列表。
示例: 输入: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。谁能告诉我为什么?
答案 0 :(得分:1)
您遇到的问题的主要原因是您的函数具有的第三个参数:这与挑战说明不符。没有第三个参数。您需要创建不带此值的返回列表。
我了解您已尝试将部分结果作为第三个参数传递,并希望在每次递归调用中扩展该部分结果,但随后出现了问题:
首先,在前两个if
块中,您假设l3
不为null,但是您不能确定是否为null。如果输入包含一个空列表,则您的代码将产生异常。
第二,如果l3
代表具有多个元素的列表,则此代码将覆盖l3
和l3.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))