要求将两个升序链表合并为一个新的升序链表,并返回合并后的链表。问题本质上是两个链表的归并操作,考察对链表的操作和合并逻辑。
解题思路:
- 创建虚拟头节点:我们需要一个虚拟头节点来简化链表的操作。虚拟头节点后会连接我们按顺序合并的节点。
- 双指针遍历链表:我们使用两个指针分别指向两个链表的当前节点,逐步比较两个链表的节点值,将较小的节点连接到新链表,并移动对应的指针。
- 处理剩余节点:当其中一个链表遍历完后,将另一个链表的剩余节点直接连接到新链表末尾。
- 返回结果:最终返回虚拟头节点的下一个节点,即合并后的链表。
C语言代码实现:
c
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
struct ListNode {
int val;
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->val < l2->val) {
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;
}
// 创建链表节点
struct ListNode* createNode(int val) {
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
newNode->val = val;
newNode->next = NULL;
return newNode;
}
// 打印链表
void printList(struct ListNode* head) {
while (head != NULL) {
printf("%d -> ", head->val);
head = head->next;
}
printf("NULL\n");
}
// 主函数
int main() {
// 创建第一个有序链表 1 -> 2 -> 4
struct ListNode* l1 = createNode(1);
l1->next = createNode(2);
l1->next->next = createNode(4);
// 创建第二个有序链表 1 -> 3 -> 4
struct ListNode* l2 = createNode(1);
l2->next = createNode(3);
l2->next->next = createNode(4);
// 合并两个链表
struct ListNode* mergedList = mergeTwoLists(l1, l2);
// 打印合并后的链表
printList(mergedList);
return 0;
}
代码讲解:
-
mergeTwoLists
函数:- 使用了一个虚拟头节点
dummy
来简化链表操作,tail
指向当前合并链表的最后一个节点。 - 通过遍历
l1
和l2
,将较小的节点附加到tail
后,并移动指针。 - 遍历结束后,将未处理完的链表直接连接到
tail
。
- 使用了一个虚拟头节点
-
createNode
函数:用于创建链表节点,方便构建链表。 -
printList
函数:用于打印链表,以方便查看结果。 -
main
函数 :创建两个有序链表,并调用mergeTwoLists
函数合并链表,最后输出合并结果。
总结:
该方法采用了迭代的方式来合并两个链表,每次比较链表节点的值,时间复杂度为 O(n+m),其中 n 和 m 分别是两个链表的长度。该算法时间复杂度和空间复杂度都较优,适合处理一般的链表合并问题。