#21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 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 均按 非递减顺序 排列
方法
- 1.双指针法
- 2.头节点法
- 3.二级指针
1.双指针法
创建两个指针,一个指针保存起始地址,另一个遍历链表,依次存储两个链表较小的数据,直到有一个链表为空,跳出遍历,因为两个链表都是非递减顺序排列,所以我们可以让遍历指针继续指向没有遍历完的另一个链表,最后返回头指针的指向的地址,因为头指针没有存储数据
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode *Head = NULL;
struct ListNode *Tail = NULL;
Head = Tail = (struct ListNode*)malloc(sizeof(struct ListNode));
while(list1&&list2)
{
if(list1->val >= list2->val)
{
Tail->next = list2;//Tail指向list2的节点
Tail = Tail->next;//Tail继续遍历,存储下一个数据
list2 = list2->next; //list2继续遍历
}
else
{
Tail->next = list1;
Tail = Tail->next;
list1 = list1->next;
}
}
Tail->next = list1 ? list1 : list2; //指向没有遍历完的链表
struct ListNode *tem = Head->next;
free(Head);//这里申请了空间,所以要释放
return tem;
}
2.头节点法
创建一个节点和一个指向它的指针,指针遍历(不断改变它的指向)存储两个链表较小的数据,最后返回头节点指向的地址
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode head;
struct ListNode *l3 = &head;
struct ListNode *l1 = list1;
struct ListNode *l2 = list2;
while(l1&&l2)
{
if(l1->val >= l2->val)
{
l3->next = l2;
l2 = l2->next;
}
else
{
l3->next = l1;
l1 = l1->next;
}
l3 = l3->next; //每当l3保存了一个数据,就让它继续指向一个新的地址来保存数据
}
l3->next = l1 ? l1 : l2;
return head.next;
}
3.二级指针
和头节点法类似,一个头指针保存数据的地址,二级指针不断遍历保存数据,最后返回头指针
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode *head = NULL, **phead = &head ;
while (list1 && list2)
{
if (list1->val < list2->val)
{
*phead = list1;
list1 = list1->next;
}
else
{
*phead = list2;
list2 = list2->next;
}
phead = &(*phead )->next; //(*phead )->next是保存数据的节点的下一个地址,方便phead不断指向下一个地址,不断遍历
}
*phead = list1 ? list1 : list2;
return head;//这里直接返回它的地址,因为head存储了数据
}