合并两个链表

本文介绍了一种使用双指针技术合并两个递增排序链表的方法,确保合并后的新链表仍保持递增排序,适用于链表长度不超过1000且节点值在-1000到1000之间的场景。

描述

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

数据范围: 0≤�≤10000≤n≤1000,−1000≤节点值≤1000−1000≤节点值≤1000

要求:空间复杂度 �(1)O(1),时间复杂度 �(�)O(n)

如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6}

或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:

img

示例1

输入:

{1,3,5},{2,4,6}

返回值:

{1,2,3,4,5,6}

示例2

输入:

{},{}

返回值:

{}

示例3

输入:

{-1,2,4},{1,3,4}

返回值:

{-1,1,2,3,4,4}

思路

一眼想到双指针,分别指向两个链表,知道一个指向null,把另一个全部加到后面。

实现

### **题目重述** 设计一个算法,将两个已排序的单向链表合并为一个新的已排序链表,要求新链表由原链表的节点拼接而成,不创建额外节点。 --- ### **详解** 假设两个链表均为**非递减有序**(即从小到大),且带头节点或不带头节点均可。我们采用**双指针法**进行合并。 #### ✅ 算法步骤(以不带头节点为例): ```c struct ListNode { int data; struct ListNode* next; }; struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) { // 创建一个虚拟头节点(哨兵),简化插入操作 struct ListNode dummy; struct ListNode* tail = &dummy; dummy.next = NULL; // 双指针遍历两个链表 while (l1 != NULL && l2 != NULL) { if (l1->data <= l2->data) { tail->next = l1; l1 = l1->next; } else { tail->next = l2; l2 = l2->next; } tail = tail->next; } // 将剩余部分接入 if (l1 != NULL) { tail->next = l1; } else { tail->next = l2; } return dummy.next; // 返回合并后的头节点 } ``` #### 🔍 解析: - 使用 `dummy` 节点避免对头节点特殊处理。 - 比较 `l1` 和 `l2` 当前节点值,较小者链接到结果链表末尾。 - 任一链表遍历完后,将另一链表剩余部分直接拼接。 - 时间复杂度:$O(m+n)$,空间复杂度:$O(1)$。 📌 若链表带头节点,则应从 `l1->next` 和 `l2->next` 开始处理,并注意头节点不参与比较。 --- ### **知识点(列出解答该问题需要的知识点)** - **双指针技术**:同时遍历两个链表,按序选取节点。 - **虚拟头节点(哨兵)技巧**:简化边界处理,统一插入逻辑。 - **链表拼接操作**:通过调整指针连接实现原地合并,无需动态分配新节点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值