题目:合并两个有序链表
题目:合并两个有序链表
描述:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
方案一·:递归。时间复杂度为```O(n+m)```,空间复杂度为```O(n+m)```
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
/*
用递归解:
1、结束条件为l1或l2为NULL,也可以作为判断l1、l2是否为空
2、当l1对应节点的值大于l2时,调用自身,此时函数的第一个参数为l1->next,
然后把该函数返回值赋值给l1->next,接着return l1;l2类似
*/
if(l1 == NULL){
return l2;//返回l2
}else if(l2 == NULL){
return l1;
}else if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
方案二:迭代。注意给出的链表没有头结点。该迭代本来想着不改变l1、l2的值,但因为l3本身就是利用l1、l2的空间,因此l1、l2的next已经发生改变了。因此优化代码作为方案三
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(l1 == NULL) return l2;
if(l2 == NULL) return l1;
struct ListNode *l3 = NULL,*pa = l1,*pb = l2,*pc = l3,*temp = NULL;
//根据两个链表的第一个结点数据决定新链表采用哪个链表的头结点开始
if(pa->val <= pb->val){//这里需要在前面判断l1、l2是否为空,要不然会出错(空指针引用)
l3 = pc = pa;
pa = pa->next;
}
else{
l3 = pc = pb;
pb = pb->next;
}
while(pa && pb){//依次处理l1、l2的当前节点,其中一个遍历为空则退出
if(pa->val <= pb->val){
temp = pa->next;
if(pc->next != pa){//连续多个节点是同链表,不用重新设置next
pa->next = pc->next;
pc->next = pa;
}
pc = pa;
pa = temp;
}
else{
temp = pb->next;
if(pc->next != pb){
pb->next = pc->next;
pc->next = pb;
}
pc = pb;
pb = temp;
}
}
pc->next = pa ? pa : pb;//插入l1或l2的剩余节点
return l3;
}
方案三:迭代优化,时间复杂度为```O(n+m)```,空间复杂度为```O(1)```
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if(l1 == NULL) return l2;
if(l2 == NULL) return l1;
//定义一个哑结点(头结点)更简单一些
struct ListNode *pre = (struct ListNode *)malloc(sizeof(struct ListNode));
if(pre == NULL) return NULL;
pre->val = -1;//手动初始化
pre->next = NULL;
struct ListNode *cur = pre;//cur指向当前节点的前一个
while(l1 && l2){
if(l1->val <= l2->val){
cur->next = l1;
l1 = l1->next;
}
else{
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;//cur跟着迁移一步
}
cur->next = l1 ? l1 : l2;//剩余节点直接并入cur->next
cur = pre->next;//cur指向合并后的头结点
free(pre);
return cur;
}
参考:
爱你如诗美丽

浙公网安备 33010602011771号