27.合并有序链表

34 阅读1分钟

题目链接

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

解法1 暴力解法

思路

最简单的办法就是将所有链表节点先按照升序给排列出来,缓存到数组当中。

然后再去遍历数组,修改每个节点的 next 指针。最后返回数组的第一个节点即可。

代码

function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null {
    if (!list1 && !list2) {
        return null;
    }
    const nodeList = [];
    let head1 = list1;
    let head2 = list2;

    while (head1 || head2) {
        if (!head1) {
            nodeList.push(head2);
            head2 = head2.next;
            continue;
        }
        if (!head2) {
            nodeList.push(head1);
            head1 = head1.next;
            continue;
        }
        if (head1.val <= head2.val) {
            nodeList.push(head1);
            head1 = head1.next;
        } else {
            nodeList.push(head2);
            head2 = head2.next;
        }
    }

    for (let i = 0; i < nodeList.length; i++) {
        nodeList[i].next = i === nodeList.length - 1 ? null : nodeList[i + 1];
    }

    return nodeList[0];
};

时空复杂度

时间复杂度:O(m + n),两个链表都需要遍历到

空间复杂度:O(m + n)

解法2 虚拟节点

思路

由于要返回新链表的头节点,所以需要先新建一个虚拟头节点。然后在此基础之上去拼接每个节点。

当有剩余链表时,由于链表本身是升序的,所以可以直接拼接。

代码

function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null {
    if (!list1 && !list2) {
        return null;
    }
    
    let dummyHead = new ListNode(-1);
    let prev = dummyHead;

    while (list1 && list2) {
        if (list1.val < list2.val) {
            prev.next = list1;
            list1 = list1.next;
        } else {
            prev.next = list2;
            list2 = list2.next;
        }
        prev = prev.next;
    }

    prev.next = !list1 ? list2 : list1; // 拼接剩下的链表,本身就是升序
    return dummyHead.next;
};

时空复杂度

时间复杂度:O(m + n)

空间复杂度:O(1),仅使用常数变量