穿越有序链表的迷宫:探索力扣“合并两个有序链表”的解题思路

news2024/11/23 1:42:16

在这里插入图片描述

本篇博客计划讲解力扣“21. 合并两个有序链表”这道题,这是题目链接。

老规矩,先来审下题干。
在这里插入图片描述
输出示例如下:
在这里插入图片描述
在这里插入图片描述

提示:
在这里插入图片描述

这道题目相当经典,同时是校招的常客。大家先思考一下,再来听我讲解。

思路:类似归并排序,把2个有序链表合并成一个新的有序链表,第一反应应该是:每次取小的结点,尾插到新的链表中。

首先定义一个新的链表,这里我定义一个哨兵位的头结点:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
}

由于后面需要反复把小的结点拿出来尾插,单链表的尾插非常麻烦,需要先遍历链表找到尾结点。但是有个简单的方法,定义一个指针,每次记录新的尾结点,省掉找尾的过程。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;
}

下面我们用2个指针,分别遍历2个链表。注意循环条件是用“并且”链接的,因为其中一个指针走到NULL就结束了。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;

    // 遍历2个链表,取小的结点尾插
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    while (cur1 && cur2)
    {
        
    }
}

每次应该比较2个结点中的数据,取小的尾插到新链表中。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;

    // 遍历2个链表,取小的结点尾插
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    while (cur1 && cur2)
    {
        if (cur1->val < cur2->val)
        {
            // 尾插cur1
        }
        else
        {
            // 尾插cur2
        }
    }
}

如何尾插呢?直接链接到tail的后面,尾插的结点成为新的tail。最后别忘了迭代,也就是让cur1或者cur2向后走一步,遍历下一个结点。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;

    // 遍历2个链表,取小的结点尾插
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    while (cur1 && cur2)
    {
        if (cur1->val < cur2->val)
        {
            // 尾插cur1
            tail->next = cur1;
            tail = cur1;
            cur1 = cur1->next;
        }
        else
        {
            // 尾插cur2
            tail->next = cur2;
            tail = cur2;
            cur2 = cur2->next;
        }
    }
}

当while循环结束时,有一个链表已经遍历完了,另外一个链表还没有遍历完。只需要把没有遍历完的链表链接到tail后面即可。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;

    // 遍历2个链表,取小的结点尾插
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    while (cur1 && cur2)
    {
        if (cur1->val < cur2->val)
        {
            // 尾插cur1
            tail->next = cur1;
            tail = cur1;
            cur1 = cur1->next;
        }
        else
        {
            // 尾插cur2
            tail->next = cur2;
            tail = cur2;
            cur2 = cur2->next;
        }
    }

    // 链接还没有遍历完的链表
    if (cur1)
    {
        tail->next = cur1;
    }
    else
    {
        tail->next = cur2;
    }
}

由于最后链接的链表的结尾一定是NULL,就不用考虑把尾置空的问题了。

下面考虑返回的问题,应该返回head->next,因为哨兵位并不存储有效数据。但在这之前,需要把哨兵位释放了。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    // 哨兵位的头结点
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = 0;
    head->next = NULL;
    // 记录尾结点,方便尾插
    struct ListNode* tail = head;

    // 遍历2个链表,取小的结点尾插
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    while (cur1 && cur2)
    {
        if (cur1->val < cur2->val)
        {
            // 尾插cur1
            tail->next = cur1;
            tail = cur1;
            cur1 = cur1->next;
        }
        else
        {
            // 尾插cur2
            tail->next = cur2;
            tail = cur2;
            cur2 = cur2->next;
        }
    }

    // 链接还没有遍历完的链表
    if (cur1)
    {
        tail->next = cur1;
    }
    else
    {
        tail->next = cur2;
    }

    // 释放哨兵位
    struct ListNode* del = head;
    head = head->next;
    free(del);
    del = NULL;

    return head;
}

在这里插入图片描述
这样就过了。是不是很简单?

总结

  1. 合并有序链表,即“归并排序”的思路:取小的尾插到新链表。
  2. 使用“哨兵位的头结点”,可以避免复杂的分类讨论。
  3. 使用tail记录尾结点,是一个常见的尾插思路。
  4. 最后别忘了释放哨兵位。

感谢大家的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.1 幂法和反幂法

学习目标&#xff1a; 如果我要学习幂法及反幂法&#xff0c;我会遵循以下步骤&#xff1a; 1. 学习理论知识&#xff1a;首先我会找到可靠的教材或者网上资源&#xff0c;学习幂法及反幂法的理论知识&#xff0c;包括其原理、公式、算法流程、收敛性等方面的内容。这些知识可…

Cadence Allegro BGA类器件扇孔操作教程

对于BGA扇孔&#xff0c;同样过孔不宜打孔在焊盘上&#xff0c;推荐打孔在两个焊盘的中间位置。很多工程师为了出线方便&#xff0c;随意挪动BGA里面过孔的位置&#xff0c;甚至打在焊盘上面&#xff0c;如图1所示&#xff0c;从而造成BGA区域过孔不规则&#xff0c;易造成后期…

3.shell脚本例子

文章目录 1.计算从1到100所有整数的和2.提示用户输入一个小于100的整数&#xff0c;并计算从1到该数之间所有整数的和3.求从1到100所有整数的偶数和、奇数和4.用户名存放在users.txt文件中&#xff0c;每行一个&#xff0c;判断文件里的用户是否存在&#xff0c;若该用户存在&a…

【Java EE】-Servlet(一) 创建Maven下的webapp项目

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【JavaEE】 分享: 在满园弥漫的沉静的光芒之前&#xff0c;一个人更容易看到时间&#xff0c;并看到自己的身影。——史铁生《我与地坛》 主要内容&#xff1a;创建一个基于maven…

【云计算•云原生】5.云原生之初识OpenStack

文章目录 OpenStack起源OpenStack基本组件HorizonNovaSwiftCinderKeystoneNeutronGlanceCeilometerTroveHeat OpenStack简单框架模型 OpenStack起源 OpenStack是一个由NASA和Rackspace合作研发并发起的&#xff0c;以Aapache许可证授权的自由软件和开放源代码项目。为公有云及…

JS 实现区块链分布式网络

JS 实现区块链分布式网络 这里主要 JS 实现区块链 实现的部分继续下去&#xff0c;对 Blockchain 这个对象有一些修改&#xff0c;如果使用 TS 的话可能要修改对应的 interface&#xff0c;但是如果是 JS 的话就无所谓了。 需要安装的依赖有&#xff1a; express body-parse…

字节跳动ByteHouse与亚马逊云科技携手打造新一代云数仓服务

随着全球化的发展&#xff0c;越来越多的中国企业开始涉足海外市场&#xff0c;开展跨境业务。在这个过程中&#xff0c;强大的数据分析能力是出海企业不可或缺的重要一环。通过有效的数据分析&#xff0c;能帮助企业更好地了解全球市场对产品的需求便于调整产品战略&#xff0…

微服务---RabbitMQ进阶(消息可靠性,延迟队列,惰性队列,集群部署)

RabbitMQ进阶(消息可靠性,延迟队列,惰性队列,集群部署) 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1.消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见…

Python每日一练(20230506) 存在重复元素I、II、III

目录 1. 存在重复元素 Contains Duplicate I 2. 存在重复元素 Contains Duplicate II 3. 存在重复元素 Contains Duplicate III &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 存在重…

项目管理-数据管理能力DCMM模型

DCMM 数据管理能力成熟度评估模型简介 DCMM&#xff08;Data Management Capability Maturity Assessment Model&#xff0c;数据管理能力成熟度评估模型&#xff09;是我国首个数据管理领域国家标准&#xff0c;将组织内部数据能力划分为八个重要组成部分&#xff0c;描述了每…

重新定义座舱智能化的下半场?谁能抓住弯道超车的窗口期

2020年&#xff0c;高通8155上车之前&#xff0c;行业的定义更多是4G联网互联网生态&#xff08;智能手机的复刻&#xff09;&#xff0c;以斑马智行为代表&#xff1b;而随着集成异构计算、高性能AI引擎&#xff08;8TOPS算力&#xff09;的高通8155密集上车&#xff0c;驱动行…

车载多屏互动联动动画版本同屏幕大小情况方案设计--众筹项目

hi&#xff0c;粉丝朋友们&#xff1a; 背景及成果展示 本节带大家来开始学习多屏幕互动的动画版本设计&#xff0c;回忆一下我们已经在之前blog和wms课程中学习了多屏互动的非动画版本如下&#xff1a; 再来看看今天我们想要实现有动画版本的成果&#xff1a; 是不是相比之…

多维时序 | MATLAB实现基于VMD-SSA-LSSVM、SSA-LSSVM、VMD-LSSVM、LSSVM的多变量时间序列预测对比

多维时序 | MATLAB实现基于VMD-SSA-LSSVM、SSA-LSSVM、VMD-LSSVM、LSSVM的多变量时间序列预测对比 目录 多维时序 | MATLAB实现基于VMD-SSA-LSSVM、SSA-LSSVM、VMD-LSSVM、LSSVM的多变量时间序列预测对比预测效果基本介绍程序设计学习总结参考资料 预测效果 基本介绍 多维时序 …

全景环视搭载率突破30%,本土供应商在细分市场突围而出

随着行泊一体、AVP等功能成为智能驾驶赛道新周期的主角&#xff0c;背后支撑落地的全景环视&#xff08;也称为360环视&#xff09;方案也不再是传统功能定义场景&#xff08;为驾驶员提供泊车及盲区辅助&#xff09;下的应用&#xff0c;同时&#xff0c;环视与周视的硬件复用…

【Mybatis-Plus笔记01】整合Springboot实现基础配置和增删改查案例

【Mybatis-Plus笔记01】整合Springboot实现基础配置和增删改查案例 【一】Mybatis-Plus的简单介绍【1】MP的特特性有哪些【2】MP的框架结构 【二】MP的使用案例&#xff08;1&#xff09;准备开发环境&#xff08;2&#xff09;添加pom依赖&#xff08;3&#xff09;编写yml配置…

基于SpringBoot+Vue实现的体检录入系统

【简介】 本体检信息录入系统采用前端&#xff1a;vue&#xff1b;后端&#xff1a;springbootmybatis-plusredismysql技术架构开发&#xff0c;前后端分离&#xff0c;容易上手。除了基本的体检结果查询、录入及导出外&#xff0c;在录入中还能对录入信息进行智能计算。 【功…

LeetCode:20. 有效的括号

20. 有效的括号 1&#xff09;题目2&#xff09;思路3&#xff09;代码4&#xff09;结果 1&#xff09;题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1…

Multi-Head self-Attention结构细节

先验知识&#xff1a; Self-Attention结构细节及计算过程https://blog.csdn.net/weixin_54039182/article/details/130515594?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22130515594%22%2C%22source%22%3A%22weixin_54039182…

分布式夺命12连问

分布式理论 1. 说说CAP原则&#xff1f; CAP原则又称CAP定理&#xff0c;指的是在一个分布式系统中&#xff0c;Consistency&#xff08;一致性&#xff09;、 Availability&#xff08;可用性&#xff09;、Partition tolerance&#xff08;分区容错性&#xff09;这3个基本…

Zotero 抓取知网文献失败解决办法梳理(针对问题:更新Translator无效,更新茉莉花插件无效,卸载Zotero无效,使用学校VPN访问知网)

Zotero 抓取知网文献失败解决办法梳理&#xff08;针对问题&#xff1a;更新Translator无效&#xff0c;更新茉莉花插件无效&#xff0c;卸载Zotero无效&#xff0c;使用学校VPN访问知网&#xff09; 问题背景解决方案一解决方案二解决方案三 说在前面&#xff1a;解决方案一和…