21、合并两个有序链表
将两个升序链表合并为一个新的 升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例1:
输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]
复制代码
示例 2:
输入: l1 = [], l2 = []
输出: []
复制代码
示例 3:
输入: l1 = [], l2 = [0]
输出: [0]
复制代码
思路
利用尾插法创建两个链表存储元素,然后再创建一个新的链表来接收两个两个链表的元素,同时遍历两个链表,当list1的val小于list2的data时,将list1的当前值加入新链表的链尾,反之则将list2的当前值加入新链表的链尾。
- 遍历两个链表,当其中一个为空的时候退出循环。
- 遍历的过程中比较两个链表头节点的数据,将较小的插入到虚拟头节点所构成链表的尾部。
- 退出循环后将不为空的链表直接连接到虚拟头节点所构成链表的尾部。
- 返回真正的头节点。
具体实现
//合并两个有序链表
#include<stdlib.h>
#include<stdio.h>
// 定义链表节点
typedef struct LNode {
int data; // 数据域
struct LNode* next; // 指针域
} LNode, * LinkList;
//尾插法创建单链表-有头结点
LinkList ListTailInsert(LinkList &L) {
int val; //设元素类型为整型
L = (LinkList)malloc(sizeof(LNode));//建立头结点
LNode* s, * r = L; //r是尾指针
while (scanf_s("%d",&val))
{
s = (LNode*)malloc(sizeof(LNode));// 待插入新节点
s->data = val;
r->next = s; // 插入操作
r = s; // 使r始终指向新的链表尾
if (getchar() == '\n')
break; // 最后一个节点元素以回车结束
}
r->next = NULL;//尾结点指针置空
return L; // 返回链表头节点
}
// 合并链表的函数
struct LNode* mergeList( LNode* list1, LNode* list2) {
LNode* head, * p, * q;
head = (struct LNode*)malloc(sizeof( LNode));
head->next = NULL;
q = head;
while (list1 != NULL && list2 != NULL) {
if (list1->data < list2->data) {
p = (LNode*)malloc(sizeof(LNode));
p->data = list1->data;
p->next = NULL;
q->next = p;
q = p;
list1 = list1->next;
}
else {
p = (LNode*)malloc(sizeof(LNode));
p->data = list2->data;
p->next = NULL;
q->next = p;
q = p;
list2 = list2->next;
}
}
if (list1 != NULL) {
q->next = list1;
}
if (list2 != NULL) {
q->next = list2;
}
return head->next->next;
}
// 打印链表的函数
void printList(LNode* head) {
LNode* current = head->next;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
运行结果
复杂度
- 时间复杂度max(O(n),O(m)) --- 其中n和m分别为两个链表的长度
- 空间复杂度O(1) --- 操作的都是原有的节点,没有额外的辅助空间