leetcode_合并链表

方法 1:递归

思路

  • 首先考虑边界情况。 特殊的,如果 l1 或者 l2 一开始就是 null ,那么没有任何操作需要合并,所以我们只需要返回非空链表。
  • 否则,我们要判断 l1 和 l2 哪一个的头元素更小,然后递归地决定下一个添加到链表里的节点。如果两个链表有任意一方为空,那么返回其中非空链表即可,递归终止
  • 代码缺点:会破坏原来链表的逻辑位置,因为是原地修改的
  • 判断某链表是否为空时,return 另一个链表是代表直接将该链表剩余部分插入合并链表中
  • NOTACK 判断两个链表的节点是否相同时的return 语句,例子:l1:1->10,l2: 2->9,递归到基例时为return l1(直接结束递归退层),此时再return l1(返回结果链表的指针)
    if(l1->val < l2->val){
        l1->next = mergeTwoLists(l1->next,l2);
        return l1;

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        else if (l2 == null) {
            return l1;
        }
        else if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        }
        else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }

    }
}

复杂度分析

时间复杂度:O(n+m)。 因为每次调用递归都会去掉 l1 或者 l2 的遍历到的元素(直到至少有一个链表为空),函数 mergeTwoList 中只会遍历每个元素一次。所以,时间复杂度与合并后的链表长度呈线性关系。

空间复杂度:O(n+m)。调用 mergeTwoLists 退出时, l1 和 l2 中每个元素都一定已经被遍历过了,所以 n+m 个栈帧会消耗 O(n+m) 的空间。

方法 2:迭代

算法

  • 首先,我们设定一个哨兵节点 “prehead” ,让我们比较容易地返回合并后的链表。
  • 我们维护一个 prev 指针,我们需要做的是调整它的 next 指针。然后,我们重复以下过程,不管我们将哪一个元素接在prev.next 后面,我们不仅要把 prev 指针向后移一个元素,两个链表的数据域在比较大小后,相应的也需要将其指针向后移动
  • 在循环终止的时候, l1 和 l2 至多有一个是非空的。由于输入的两个链表都是有序的,所以不管哪个链表是非空的,它包含的元素都比前面已经合并链表中的元素都要大。so 我们需将剩下的非空链表接在已经合并链表的后即可
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // maintain an unchanging reference to node ahead of the return node.  维护一个不会改变引用的节点,做返回合并后的链表使用
        ListNode prehead = new ListNode(-1);

        ListNode prev = prehead;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;
                l1 = l1.next;
                
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }

        // exactly one of l1 and l2 can be non-null at this point, so connect the non-null list to the end of the merged list.
        prev.next = l1 == null ? l2 : l1;

        return prehead.next;
    }
}

复杂度分析

时间复杂度:O(n+m) 。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, while循环的次数等于两个链表的总长度。所有其他工作都是常数级别的,所以总的时间复杂度是线性的。

空间复杂度:O(1) 。迭代的过程只会产生几个指针,所以它所需要的空间是常数级别的。??? NOT ACK 应该还申请了一个链表空间用来存储合并链表才对

猜你喜欢

转载自blog.csdn.net/sinat_40701582/article/details/106651102