原题链接🔗:合并两个有序链表
难度:简单⭐️
题目
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 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 均按 非递减顺序 排列
题解
迭代法
- 题解:
合并两个有序链表的问题可以通过多种方法解决,但最常见的方法是使用迭代。以下是解决这个问题的一般思路:
定义节点结构:首先定义链表节点的数据结构,通常包含节点的值和指向下一个节点的指针。
初始化哑节点:创建一个哑节点(dummy node),它将作为合并后链表的前驱节点。使用哑节点的好处是可以直接返回哑节点的下一个节点作为合并后的链表的头节点。
迭代合并:使用两个指针分别指向两个链表的当前节点,比较它们的值,将较小的节点连接到结果链表上,并将该节点的指针向前移动一位。
处理剩余节点:当其中一个链表遍历完成后,将另一个链表剩余的部分直接连接到结果链表的末尾。
返回结果:返回哑节点的下一个节点,即合并后链表的头节点。
-
复杂度:时间复杂度O(m+n),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的;空间复杂度O(1),只需要常数的空间存放若干变量。
-
过程:
- 创建哑节点:ListNode* dummy = new ListNode(0);
- 初始化尾指针:ListNode* tail = dummy;
- 迭代比较:使用一个循环,当两个链表的当前节点都不为空时,进行以下操作:
- 比较两个链表当前节点的值。
- 将较小节点连接到tail的后面。
- 移动tail和较小节点的指针。
- 连接剩余节点:当其中一个链表的节点为空时,将另一个链表的剩余部分直接连接到tail后面。
- 返回结果:返回dummy->next作为合并后链表的头节点。
- c++ demo:
#include <iostream>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// 创建一个哑节点,作为合并后链表的起始点
ListNode* dummy = new ListNode(0);
ListNode* tail = dummy;
// 用哑节点的 next 指针来逐步构建合并后的链表
while (l1 != nullptr && l2 != nullptr) {
if (l1->val < l2->val) {
tail->next = l1;
l1 = l1->next;
}
else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}
// 将剩余的非空链表接在合并后的链表后面
if (l1 != nullptr) {
tail->next = l1;
}
else {
tail->next = l2;
}
// 返回合并后的链表的头节点
ListNode* result = dummy->next;
delete dummy; // 释放哑节点
return result;
}
};
int main() {
// 测试代码
ListNode* l1 = new ListNode(1);
l1->next = new ListNode(2);
l1->next->next = new ListNode(4);
ListNode* l2 = new ListNode(1);
l2->next = new ListNode(3);
l2->next->next = new ListNode(4);
Solution solution;
ListNode* mergedList = solution.mergeTwoLists(l1, l2);
// 打印合并后的链表
while (mergedList != nullptr) {
std::cout << mergedList->val << " ";
ListNode* temp = mergedList;
mergedList = mergedList->next;
delete temp; // 释放节点
}
std::cout << std::endl;
return 0;
}
- 输出结果:
1 1 2 3 4 4