【Leetcode之21. 合并两个有序链表】详解

本文详细解析了LeetCode第21题的解决方案,即如何合并两个已排序的链表。通过比较链表节点的值,进行尾部插入操作,最终形成一个新的升序链表。文章提供了详细的思路分析和代码实现,特别关注了处理链表为空和不等长的情况。
摘要由CSDN通过智能技术生成

【Leetcode之21. 合并两个有序链表】详解


题目概述

[刷题链接](https://leetcode.cn/problems/merge-two-sorted-lists/):

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述
在这里插入图片描述

提示:以下是本篇文章正文内容,下面案例可供参考

一、思路分析

本题较容易想到的方法是取小值尾插
对链表尾插操作不熟练的读者可以前往作者的博客进一步学习,链接如下
《她逃,他追,她们插翅难飞》之节点的爱恨情仇

尝试

我们既然要进行尾插,首先需定义两个结构体指针tail和head,前者的作用是进行尾部节点的更新,后者的作用是更新头指针,当所有尾插操作结束后返回head

    struct ListNode*head=NULL;
    struct ListNode*tail=NULL;

图解

取list1->val和list2->val进行比较
在这里插入图片描述
此时都是1,不妨取list2进行尾插
因为tail和head为空,此时链表为空,故进行下列操作

if(tail==NULL)
        {
            head=tail=list1;
        }

在这里插入图片描述
再将list2后移动

list2=list2->next;

在这里插入图片描述
再次进行比较list1和list2
1<3
故对此时list1指向的元素进行尾插,再更新tail的位置

tail->next=list1;
tail=tail->next;

在这里插入图片是描述
更新list1

 list1=list1->next;

在这里插入图片描述
继续如上操作,对比发现list1->val< list2->val,故取list1尾插,更新tail

 tail->next=list1;
 tail=tail->next;

在这里插入图片描述
再更新list1

 list1=list1->next;

在这里插入图片描述
读者朋友读到这里,应该会感到冗长,别放弃,我们一起过一遍流程
list1->val>list2->val
应当取list2尾插
更新tail和list2

         tail->next=list2;
         tail=tail->next;
         list2=list2->next;

在这里插入图片描述

此时又回到了开头那样,list1->val=list2->val
相同的时候,我们不妨取list2头插
重复以上操作

 tail->next=list2;
 tail=tail->next;
 list2=list2->next;

在这里插入图片描述
难点,此时list2为空,不能进行解引用操作
前面的逻辑和解决思路无效
应该采用如下解决方法

  • 如果list1不为空,将tail与list1连接
if(list1)
{
    tail->next=list1;
}
  • 如果list2不为空,将tail与list2连接
if(list2)
{
    tail->next=list2;
}

思考

假如两个链表中一个为空,即一开始list1和list2中有一个为空,应该在循环之前加一次判断,如果其中一种链表为空,返回令一个链表的list

if(list1==NULL)
{
    return list2;
}
if(list2==NULL)
{
    return list1;
}

二、代码整合

代码如下(示例):

/**
 * 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;
if(list1==NULL)
{
    return list2;
}
if(list2==NULL)
{
    return list1;
}
while(list1 && list2)
{
    if(list1->val<list2->val)
    {
        if(tail==NULL)
        {
            head=tail=list1;
        }
        else
        {
            tail->next=list1;
            tail=tail->next;
        }
        list1=list1->next;
    }
    else
    {

        if(tail==NULL)
        {
            head=tail=list2;
        }
        else
        {
            tail->next=list2;
            tail=tail->next;
        }
        list2=list2->next;
    }
    //如果list1或者list2其中某个链表结束,即链表不等长
    //则执行下列代码,让其中没有遍历结束的链表继续进行
}
if(list1)
{
    tail->next=list1;
}
if(list2)
{
    tail->next=list2;
}
return head;
}

运行结果
在这里插入图片描述

总结

这是一道很经典的面试题,希望读者朋友们能很好得掌握:

日拱一卒 功不唐捐
————————————————————— 胡适之

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江财菊圃路彭家桥C++一霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值