当前位置: 首页 > news >正文

010 【入门】链表入门题目-合并两个有序链表

🔗 合并两个有序链表 | [算法]-[中级]-[链表]

▶ JDK8+ | ⏱️ O(m+n)

核心代码实现

package class010;// 将两个升序链表合并为一个新的升序链表并返回
// 新链表是通过拼接给定的两个链表的所有节点组成的
// 测试链接 : https://leetcode.cn/problems/merge-two-sorted-lists/
public class MergeTwoLists {// 链表节点定义public static class ListNode {public int val;public ListNode next;public ListNode(int val) {this.val = val;}public ListNode(int val, ListNode next) {this.val = val;this.next = next;}}class Solution {/*** 合并两个有序链表的迭代解法* 时间复杂度: O(m+n),其中m和n分别是两个链表的长度* 空间复杂度: O(1),只需要常数级别的指针空间* * @param head1 第一个链表的头节点* @param head2 第二个链表的头节点* @return 合并后链表的头节点*/public static ListNode mergeTwoLists(ListNode head1, ListNode head2) {// 边界条件:如果任一链表为空,直接返回另一个链表if (head1 == null || head2 == null) {return head1 == null ? head2 : head1;}// 选择头节点值较小的链表作为新链表的头ListNode head = head1.val <= head2.val ? head1 : head2;// cur1指向已选择头部链表的下一个节点ListNode cur1 = head.next;// cur2指向另一个链表的头节点ListNode cur2 = head == head1 ? head2 : head1;// pre指针用于追踪新链表的当前末尾节点ListNode pre = head;// 遍历两个链表,直到其中一个到达末尾while (cur1 != null && cur2 != null) {if (cur1.val <= cur2.val) {pre.next = cur1; // 连接cur1节点cur1 = cur1.next; // 移动cur1指针} else {pre.next = cur2; // 连接cur2节点cur2 = cur2.next; // 移动cur2指针}pre = pre.next; // 移动pre指针到新末尾}// 将剩余的未处理节点连接到新链表末尾pre.next = cur1 != null ? cur1 : cur2;return head;}}
}

关联知识图谱

1. 算法思路可视化
比较两链表头节点值
初始化三指针
选择较小值节点
一个链表到达末尾
返回合并后链表
边界检查
选择头节点
迭代合并
连接剩余
2. 三指针策略图解
pre  → [ ] → [ ] → ...↑headcur1 → [ ] → [ ] → ...cur2 → [ ] → [ ] → ...
3. 递归解法对比
// [递归解法] 更简洁但空间复杂度为O(m+n)
public ListNode mergeTwoListsRecursive(ListNode l1, ListNode l2) {// 基本情况:如果一个链表为空,返回另一个链表if (l1 == null) return l2;if (l2 == null) return l1;// 递归合并:选择较小的头节点,并递归合并剩余部分if (l1.val < l2.val) {l1.next = mergeTwoListsRecursive(l1.next, l2);return l1;} else {l2.next = mergeTwoListsRecursive(l1, l2.next);return l2;}
}

行动指南

1. 优化与变体
  • [优化] 使用哨兵节点简化代码:
// [推荐] 使用哨兵节点简化边界处理
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(-1); // 哨兵节点ListNode current = dummy;while (l1 != null && l2 != null) {if (l1.val <= l2.val) {current.next = l1;l1 = l1.next;} else {current.next = l2;l2 = l2.next;}current = current.next;}// 连接剩余部分current.next = l1 != null ? l1 : l2;return dummy.next;
}
2. 安全与性能考量
  • [警告] 在多线程环境中操作链表需要额外同步机制
  • [注意] 对于超长链表,递归解法可能导致栈溢出,迭代解法更安全
  • [技巧] 使用哨兵节点可以简化代码,但会增加少量空间开销
3. 相关题目与应用

🔗 相关题目:

  • [LeetCode 23] 合并K个升序链表
  • [LeetCode 148] 排序链表
  • [面试经典] 链表归并排序实现

🚀 效率工具:

  • 调试技巧: 使用条件断点检查链表循环引用 node == node.next

▶ 扩展问题:如何在O(1)空间复杂度下合并K个有序链表?

http://www.lqws.cn/news/543709.html

相关文章:

  • Linux驱动学习day9(异常与中断处理)
  • 华为云Flexus+DeepSeek征文|基于Dify构建故事绘本制作工作流
  • Spark 写入hive表解析
  • Spring Boot项目开发实战销售管理系统——系统设计!
  • 知名流体控制解决方案供应商“永盛科技”与商派ShopeX达成B2B商城项目合作
  • iOS 远程调试与离线排查实战:构建非现场问题复现机制
  • 报道称CoreWeave洽谈收购Core Scientific,后者涨超30%
  • NV025NV033美光固态闪存NV038NV040
  • 《二分枚举答案(配合数据结构)》题集
  • Python Selenium 滚动到特定元素
  • Selenium基本用法
  • Spring Boot 性能优化与最佳实践
  • 6.27_JAVA_面试(被抽到了)
  • 洛谷P5021 [NOIP 2018 提高组] 赛道修建
  • 深入理解 Linux `poll` 模型:`select` 的增强版
  • 记录一次飞书文档转md嵌入vitepress做静态站点
  • 微信小程序进度条progress支持渐变色
  • Stable Diffusion入门-ControlNet 深入理解-第三课:结构类模型大揭秘——深度、分割与法线贴图
  • 【LeetCode 热题 100】42. 接雨水——(解法三)单调栈
  • FPGA在嵌入式图像处理中的深度应用!
  • 深圳中青宝互动网络股份有限公司游戏运维工程师面试题(笔
  • python实战项目79:采集知乎话题下的所有回答
  • 【用户权限】超级用户(二)
  • win7实现永恒之蓝ms17_010漏洞之445端口
  • matlab实现相控超声波成像
  • 推荐一个基于C#开发的跨平台构建自动化系统!
  • 通信无BUG,ethernet ip转profinet网关,汽车焊接设备通信有心机
  • 面向大语言模型幻觉的关键数据集:系统性综述与分类法_DEEPSEEK
  • Spring Boot整合Redis指南
  • 从电费追缴到碳减排:一个预付费系统如何重塑校园能源生态