21.合并两个有序链表
思路
使用哨兵节点简化处理:
创建一个值为 -1 的哨兵节点 l3,它不会出现在最终结果中,但能让我们避免特判空链表或头节点的问题。
双指针比较大小,逐个接入新链表:
每次比较两个链表当前节点的值,将较小的那个接到新链表末尾,然后向前移动对应链表指针。
拼接剩余节点:
当其中一个链表遍历完后,另一个链表中剩下的节点一定是升序的,直接接在新链表后即可。
返回哨兵节点后的第一个节点:
l3.next 即为合并后链表的实际头节点。
题解
* 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* l1, ListNode* l2) {// 创建一个哨兵节点 l3,初始值设为 -1(值无所谓,只是占个位置)// p 是结果链表的当前尾节点,初始指向哨兵节点ListNode l3(-1), *p = &l3;// 双指针分别指向两个链表ListNode* p1 = l1, *p2 = l2;// 只要两个链表都未遍历完,就继续比较while(l1 != nullptr && l2 != nullptr){if(l1->val < l2->val){// 把 l1 当前节点接到结果链表后p->next = l1;// 移动 l1 指针到下一个节点l1 = l1->next;}else{// 把 l2 当前节点接到结果链表后p->next = l2;// 移动 l2 指针到下一个节点l2 = l2->next;}// p 始终指向新链表的尾节点p = p->next;}// 如果 l1 还有剩余,就接到 p 后面if(l1 != nullptr){p->next = l1;}// 如果 l2 还有剩余,就接到 p 后面if(l2 != nullptr){p->next = l2;}// 返回哨兵节点后面第一个有效节点return l3.next;}
};