• Leetcode21:合并两个有效链表


    原题地址:. - 力扣(LeetCode)

    题目描述

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

    示例 1:

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

    示例 2:

    输入:l1 = [], l2 = []
    输出:[]
    

    示例 3:

    输入:l1 = [], l2 = [0]
    输出:[0]
    

    提示:

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

    实现思路

    1. 输入检查:首先检查两个链表的头节点。如果一个链表为空,直接返回另一个链表的头节点。
    2. 优先队列(最小堆):使用一个优先队列来存储两个链表中的节点。通过重写比较器,确保队列中的节点按值升序排列。
    3. 遍历链表:将两个链表中的所有节点依次加入优先队列。在添加节点后,断开当前节点与后继节点的连接,以避免内存泄漏。
    4. 构建合并链表:从优先队列中依次取出节点,构建合并后的链表。使用一个临时节点指针来维护链表的尾部。
    5. 返回结果:返回合并后链表的头节点。

    源码实现

    1. /**
    2. * Definition for singly-linked list.
    3. * public class ListNode {
    4. * int val;
    5. * ListNode next;
    6. * ListNode() {}
    7. * ListNode(int val) { this.val = val; }
    8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    9. * }
    10. */
    11. class Solution {
    12. public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    13. // 检查链表是否为空
    14. if (l1 == null) { return l2; } // 如果l1为空,返回l2
    15. if (l2 == null) { return l1; } // 如果l2为空,返回l1
    16. // 使用优先队列来存储链表节点
    17. PriorityQueue node = new PriorityQueue<>(new Comparator() {
    18. @Override
    19. public int compare(ListNode o1, ListNode o2) {
    20. return o1.val - o2.val; // 按节点值升序排列
    21. }
    22. });
    23. // 遍历两个链表并将节点加入优先队列
    24. while (l1 != null || l2 != null) {
    25. if (l1 != null) {
    26. node.add(l1); // 添加l1节点
    27. ListNode next = l1.next; // 记录下一个节点
    28. l1.next = null; // 断开当前节点与后继的连接
    29. l1 = next; // 移动到下一个节点
    30. }
    31. if (l2 != null) {
    32. node.add(l2); // 添加l2节点
    33. ListNode next = l2.next; // 记录下一个节点
    34. l2.next = null; // 断开当前节点与后继的连接
    35. l2 = next; // 移动到下一个节点
    36. }
    37. }
    38. // 从优先队列中取出节点构建合并链表
    39. ListNode result = node.poll(); // 取出第一个节点作为合并链表的头
    40. ListNode temp = result; // 使用temp指针维护合并链表的尾部
    41. while (node.peek() != null) {
    42. ListNode tag = node.poll(); // 取出下一个节点
    43. temp.next = tag; // 将当前节点链接到合并链表的尾部
    44. temp = tag; // 更新temp指针
    45. }
    46. return result; // 返回合并后的链表头
    47. }
    48. }

    复杂度分析

    • 时间复杂度:O((m + n) log(m + n)),其中 m 和 n 分别是两个链表的长度。我们将所有节点加入优先队列的时间复杂度为 O(m + n),而每次从优先队列中取出节点的时间复杂度为 O(log(m + n)),因此总体复杂度为 O((m + n) log(m + n))。

    • 空间复杂度:O(m + n),我们在优先队列中存储了两个链表的所有节点,因此需要 O(m + n) 的空间。

  • 相关阅读:
    云原生:深入掌握Docker日志管理:高效策略与最佳实践
    Vue Vuex模块化编码
    iOS编译openmp
    理解ffmpeg
    windows终端调用clangd出现Missing Content-Length header的问题
    Ubuntu18保姆级教程及其jdk和hadoop安装含资源
    Android Glide 3.8 常见方法总结 【圆角、下载、回调】
    【JVM】Java虚拟机
    python数据结构与算法-06_算法分析
    论文阅读:BEVBert: Multimodal Map Pre-training for Language-guided Navigation
  • 原文地址:https://blog.csdn.net/qq_36070104/article/details/143416965