算法-合并两个有序链表

140 阅读2分钟

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

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

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

迭代

 public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //这是一个哨兵指针,作用为了返回合并的链表
        ListNode prev = new ListNode();
        //之前当前l1 和 l2中较小的值
        ListNode header = prev;

        while (l1 != null || l2 != null) {

            if (l1 == null) {
                header.next = l2;
                header = l2;
                l2 = l2.next;
            } else if (l2 == null) {
                header.next = l1;
                header = l1;
                l1 = l1.next;
            } else if (l1.val <= l2.val) {
                header.next = l1;
                header = l1;
                l1 = l1.next;
            } else {
                header.next = l2;
                header = l2;
                l2 = l2.next;
            }
        }
        return prev.next;

    }

首先定义一个哨兵prev,记录位置,方便返回整个链表,用header指向l1l2最小的值,指向后,对应的链表向后移动,然后进行下一轮比较。

复杂度分析

  • 时间复杂度:O(n+m))O(n + m)), n 和 m 分别为两个链表的长度。每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。

  • 空间复杂度:O(1)O(1)。常数的空间存放若干变量。

迭代2

迭代方法一有一个缺陷,那就是当l1l2其中一个已经迭代完成了,那么剩下的元素都在一个链表中,是无需再进行迭代判断,直接进行合并即可。

     //这是一个哨兵指针,作用为了返回合并的链表
        ListNode prev = new ListNode();
        //之前当前l1 和 l2中较小的值
        ListNode header = prev;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                header.next = l1;
                l1 = l1.next;
            } else {
                header.next = l2;
                l2 = l2.next;
            }
            header = header.next;
        }

        // 当其中一个链表为null时,代表剩下的元素都在另外一个链表中,直接合并即可
        header.next = l1 == null ? l2 : l1;

        return prev.next;

复杂度分析

  • 时间复杂度:O(n+m))O(n + m)), n 和 m 分别为两个链表的长度。每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。

  • 空间复杂度:O(1)O(1)。常数的空间存放若干变量。