21. 合并两个有序链表

156 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

21. 合并两个有序链表

力扣题目链接

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例一:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • 100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

思路:

有序链表的合并问题,是最经典的链表题目,考查链表的遍历与末尾的判断。

这里我们声明一个哨兵节点作为新链表的起始位置。然后开始比较两个链表的值,将具有较小值的链表节点赋值给新链表当前节点的next指针。然后新链表和待排序链表的当前指针都向后移动一位继续下个节点的比较。

当list1或者list2为空时,跳出循环。此时可能还有另一个链表的指针还没有走到末尾,因此直接将尚未走完的链表赋值给新链表当前节点的next指针。

最后返回哨兵节点的下一个节点引用即可。因为哨兵节点是用于串联起一个链表,最终结果中不能包含该节点。

完整代码如下:

哨兵节点

/**
 * 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) {
    let head = new ListNode(0); // 初始化哨兵节点
    let cur = head; // 指向cur指针
    while(list1 && list2) { // 找到两个链表的较小者,追加到新链表中
        if (list1.val < list2.val) {
            cur.next = list1; // cur的next指向较小节点
            list1 = list1.next; // 头部指向下个节点
        } else {
            cur.next = list2;
            list2 = list2.next;
        }
        cur = cur.next; // 指向下一个节点
    }
    cur.next = list1 || list2; // 继续拼接尚未遍历完的链表
    return head.next; // 返回哨兵节点的下一个节点
};

总结

本题考查有序链表的合并。在链表的排序中,也会使用到有序链表的合并,同时还用到了二分法以及归并排序。是一道值得掌握的算法题。