一、题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 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
均按 非递减顺序 排列
二、分析
输入:2个分别指向两个链表的头节点的指针
返回:1个指向合并后的链表的头节点的指针
目的:将两个值按照 非递减序列 排序的链表按照值从小到大的顺序合并成一个新链表
初步想法:
题目的描述和“归并排序”的做法比较像,归并排序在排序前会将要排序的集合分成两部分然后对两部分分别排序,之后再将两个有序的集合合并成一个新集合。而这道题已经完成了对两个集合排序的部分剩下要完成的只有合并了,以及要使用链表相关的操作。
详细一点的想法大概是这样:创建一个新链表用来存放最终结果,同时创建两个专门指向两个链表的指针用于遍历它们,它们初始都指向各自链表的头节点,在经过比较之后将值较小的结点加入到新链表中,同时该被取走结点的链表对应指针往后移一位,然后进行下一次比较;循环持续到任一链表为空(任一指针指向空指针)然后将新链表的尾指针指向还未空的链表所对应的指针
困难或出错的地方:
1.这道题目要是让很熟悉排序算法的人来做肯定瞬间就能有思路,但我还是查了一下才知道呢,所以按理来说这道题还是主要考察能不能将归并排序的合并部分用链表形式实现
2.一开始在思考该怎么在循环中让结果链表的第一个结点就是两个链表比较后选出的结点时思考了比较久,最后还是在开始循环检视两个链表之前就先比较了一下两个链表的第一个结点然后将它作为结果链表的第一个结点了。这样貌似也没有很费事,反倒可以和检查输入是否非空的if放在一起
3.关于创建一个结果链表的部分,一开始设想的是只需要创建一个新指针result指向结果链表的头结点就可以了,但之后发现还需要一个指针用来指向“当某个输入链表被读取完毕时“的结果链表尾结点,如果移动result到尾结点的话就没办法再找到结果指针的头结点了啊!所以最后还是又创建了一个指针current用来指向那个暂时的尾结点以及在循环中构建结果链表,result就只承担指向结果链表头指针的任务了
三、算法实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* result; // 指向结果链表头的指针
ListNode *temp1 = list1;
ListNode *temp2 = list2;
// 先向结果链表中添加第一个结点
if (temp1 == nullptr) { //链表1为空直接范围链表2
return temp2;
}
else if (temp2 == nullptr) { // 直接返回链表1
return temp1;
}
else if (temp1->val <= temp2->val) { // 链表1头结点小于链表2
result = temp1;
temp1 = temp1->next;
}
else { // 链表2头结点小于链表1
result = temp2;
temp2 = temp2->next;
}
ListNode *current = result; // 用来在循环过程中向结果链表添加结点,最终会指向结果链表“暂时的尾结点”
while(temp1!=nullptr&&temp2!=nullptr){
if(temp1->val<=temp2->val){ // 如果链表1当前结点更小
current->next = temp1; // 将链表1的这个结点放入结果链表,同时指针1向后移一位,指针2不动并参与下一轮比较
temp1 = temp1->next;
}
else {
current->next = temp2; // 链表2当前结点更小的操作
temp2 = temp2->next;
}
current = current->next; // 为了在读取完某一链表时让current指针指向当前结果链表的尾结点所以移动
}
if(temp1==nullptr){
current->next = temp2;
}
else if(temp2==nullptr){
current->next = temp1;
}
return result;
}
};