【LeetCode刷题】将两个升序链表合并为一个新的升序链表

题记

转眼已过去很多年了,登录园子看到几年前自己记录的笔记,感慨万千,庆幸的是自己还在这行没有放弃,不过,随着工作经验的积累,感觉自己越来越无知,索性最近又捡起9年前刚毕业工作那会儿无知的劲儿,来刷题换换脑子~~~

题目描述

该题来自LeetCode第21题:合并两个有序链表
https://leetcode-cn.com/problems/merge-two-sorted-lists/

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

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

image

解题思路

  1. 创建一个虚拟头节点,其下一个节点为从L1, L2的头节点中选取值较小的节点,假设合并完成,则返回辅助节点的下一个节点,即为最终链表的头节点;
  2. 新建一个辅助节点,比较L1, L2当前节点的值,其下一个节点也指向L1, L2中值较小的节点,向后移动较小值的节点,同时辅助节点也后移一位;
  3. 重复第2步,直至L1, L2其中一个链表遍历完成, 辅助节点的下一个节点指向剩下未遍历完成的链表即可。

总结下来,其实就像是拿着一个针(辅助节点)穿珠子,比较两串珠子头上一颗珠子的大小,把小的穿上(辅助节点的下一个节点指向二者小的节点),重复该动作,到其中一串珠子穿完,剩下的无需比较直接穿到后面即可。

通过文字描述还是比较抽象,通过画图的形式来演示每一步,相对来说,就比较好理解了,我按照上述步骤画了一下推演图,如下:

  1. compare比较链表头节点大小
  2. pre下一个节点指向值小的链表
  3. 较小的链表头向后移动一位
  4. pre也向后移动一位(指向合并后的链表尾节点)

image

Java代码实现

public class MergeTwoLists {

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        // 虚拟头节点,下一个节点指向L1,L2二者中较小的头节点
        ListNode preHead = new ListNode(-1);
        // 辅助节点引用
        ListNode pre = preHead;
        while (l1 != null && l2 != null) {
            // 辅助节点的下一个节点为值小的节点
            // 较小值的节点向后移动
            if (l1.val > l2.val) {
                pre.next = l2;
                l2 = l2.next;
            } else {
                pre.next = l1;
                l1 = l1.next;
            }
            // 辅助节点也同步向后移动
            pre = pre.next;
        }
        // 如果其中一个链表已经结束,则剩下节点接到后面即可
        pre.next = l1 == null ? l2 : l1;
        // 返回虚拟头节点的下一个节点
        return preHead.next;
    }
}

总结

该解法的时间复杂度为O(m+n), m、n分别为链表L1、L2的长度;空间复杂度为 O(1), 引入了辅助节点,没有利用其它额外的空间。另外,还有另外一种解法是递归,俗话说,递归是一看就会,一写就跪,等有空了再试试。

结束...

原文地址:https://www.cnblogs.com/beetle-shu/p/15025378.html