
方法一:递归
js
/**
* 核心思路:递归
* 1. 终止条件:当其中一个链表为空时,直接返回另一个链表(剩余部分)
* 2. 递归过程:比较两个链表当前节点的值,选择较小的节点作为当前节点,
* 并将该节点的next指向后续递归合并的结果
* 3. 返回值:每次递归返回的是当前选择的、已经处理好后续链接的节点
*/
var mergeTwoLists = function (list1, list2) {
// 递归终止条件1:如果list1为空,直接返回list2(剩余的有序部分)
// 注:如果list2也为空,这里会返回null,符合"都为空则返回空"的要求
if (list1 === null) return list2
// 递归终止条件2:如果list2为空,直接返回list1(剩余的有序部分)
if (list2 === null) return list1
// 核心递归逻辑:比较当前两个节点的值,选择较小的节点
if (list1.val < list2.val) {
// 如果list1的当前节点更小,那么list1的next应该指向
// "list1的下一个节点"和"list2当前节点"合并后的结果
list1.next = mergeTwoLists(list1.next, list2)
// 返回当前选择的list1节点(作为合并后链表的当前节点)
return list1
}
// 走到这里说明 list2.val <= list1.val(list2的当前节点更小或相等)
// 同理,list2的next应该指向"list1当前节点"和"list2的下一个节点"合并后的结果
list2.next = mergeTwoLists(list1, list2.next)
// 返回当前选择的list2节点(作为合并后链表的当前节点)
return list2
}方法二:迭代
为什么需要prev指针:
prev相当于合成后链表的最新节点,而i,j相当于待合成节点
js
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
// 迭代
var mergeTwoLists = function (list1, list2) {
const prehead = new ListNode(null)
let prev = prehead
let i = list1,
j = list2
while (i !== null && j !== null) {
if (i.val < j.val) {
prev.next = i
i = i.next
} else {
prev.next = j
j = j.next
}
prev = prev.next
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = i === null ? j : i
return prehead.next
}