题目链接: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 均按 非递减顺序 排列。
代码(c++):
方案一:在list1链表上原地操作。
定义一个虚拟头节点,然后比较list1和list2当前节点的值,如果list2的值更小,则将list2的next指向改为list1,否则不用改。虚拟头节点的作用是为了防止list1为空的情况,后面还需要加一个判断,如果list1为空,list2不为空,那么直接将list2加在list1后面,否则不用操作。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* dummyHead = new ListNode(0, list1); //哨兵节点
ListNode* node = dummyHead;
//在list1链表原地操作
while (list1 && list2) {
if (list1->val > list2->val) {
ListNode* cur = list2->next; //记录list2节点未改变引用时的next节点
node->next = list2;
list2->next = list1; //将list2节点指向改为指向list1
list2 = cur; //更新list2为原先的next节点
}
else {
list1 = list1->next;
}
node = node->next;
}
if (list2) { //如果list2长度大于list1,则直接放在list1后面
node->next = list2;
}
ListNode* ans = dummyHead->next;
delete dummyHead;
return ans;
}
};
方案二:“新建”一条链表。
当 list1 和 list2 都不是空链表时,判断 list1 和 list2 哪一个链表的头节点的值更小,将较小值的节点添加到结果里,当一个节点被添加到结果里之后,将对应链表中的节点向后移一位。在循环终止的时候, list1 和 list2 至多有一个是非空的。由于输入的两个链表都是有序的,所以不管哪个链表是非空的,它包含的所有元素都比前面已经合并链表中的所有元素都要大。这意味着我们只需要简单地将非空链表接在合并链表的后面,并返回合并链表即可。
//“新建”一个链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* dummyHead = new ListNode(); //哨兵节点
ListNode* node = dummyHead;
while (list1 && list2) {
if (list1->val < list2->val) { //如果list1当前节点的值小于list2当前节点的值,那么将list2的值加入结果
node->next = list1;
list1 = list1->next;
}
else {
node->next = list2;
list2 = list2->next;
}
node = node->next;
}
//至多有一个链表是非空的
node->next = list1 ? list1 : list2;
ListNode* head = dummyHead->next;
delete dummyHead;
return head;
}
};
方案三:递归。
如果 list1 或者 list2 一开始就是空链表 ,那么没有任何操作需要合并,所以我们只需要返回非空链表。否则,我们要判断 list1 和 list2 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的节点。如果两个链表有一个为空,递归结束。
//递归
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if (!list1) {
return list2; //返回非空链表list2
}
else if (!list2) {
return list1; //返回非空链表list1
}
else if (list1->val < list2->val) { //list1当前节点的值小于list2当前节点的值,递归list1,返回list1当前节点
list1->next = mergeTwoLists(list1->next, list2);
return list1;
}
else {
list2->next = mergeTwoLists(list1, list2->next);
return list2;
}
}
};