【刷题之路Ⅱ】LeetCode 24. 两两交换链表中的节点

news2024/12/25 9:24:28

【刷题之路Ⅱ】LeetCode 24. 两两交换链表中的节点

  • 一、题目描述
  • 解题
    • 1、方法1——递归
      • 1.1、思路分析
      • 1.2、代码实现
    • 2、方法2——迭代
      • 2.1、思路分析
      • 2.2、代码实现
    • 3、方法3——交替的尾插
      • 3.1、思路分析
      • 3.2、代码实现

一、题目描述

原题连接: 24. 两两交换链表中的节点
题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。
你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

在这里插入图片描述
输入: head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

输入: head = []
输出:[]

示例 3:

输入: head = [1]
输出:[1]

提示:
链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100

解题

1、方法1——递归

1.1、思路分析

想要理解递归的思路,我们可以先从链表中只有两个节点的情况入手:
在这里插入图片描述
当链表中只有两个节点时,进行两两交换其实很简单,只需要再创建一个新头指针newhead,然后让newhead指向原链表的第二个节点(即head->next),再将原链表的第一个节点尾插到后面即可:
在这里插入图片描述
但其实我们把这种方法推广到更长的链表中也是可行的,即我们每次递归都优先交换链表的前两个节点,而剩下的节点的交换我们就用递归来实现,如图:
在这里插入图片描述
我们先让newhead指向原链表的第二个节点,置于第二个节点后的节点的交换就交给递归来完成,完成后再让head的next指向剩下的链表,及执行head->next = swapPairs(newhead->next),最后在将第一个节点和第二个节点连接起来:
在这里插入图片描述

1.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

struct ListNode* swapPairs(struct ListNode* head){
    if (NULL == head || NULL == head->next) { // 如果链表为空或只有一个节点,直接返回head即可
        return head;
    }
    struct ListNode *newhead = head->next;
    head->next = swapPairs(newhead->next);
    newhead->next = head;
    return newhead;
}

2、方法2——迭代

我想一定有些朋友在看了上面的递归解法后还是会一头雾水,没关系,我这里还有个相对更容易理解的思路,其实也就是在原链表上动刀子。

2.1、思路分析

我们可以先创建一个辅助节点dumbNode,初始时我们让dumbNode的next指向head:
在这里插入图片描述
之所以要创建这个辅助节点,其实就是为了更方便的解决链表中只有两个节点的情况,在后面我们基本就用不到dumbNode了。
同时我们还需要三个指针cur,Node1,Node2,初始时我们让cur指向dumbNode:
在这里插入图片描述
每一次迭代我们让Node1和Node2指向cur的后两个节点,然后将Node1和Node2的位置交换,具体交换方式如下:
在这里插入图片描述
然后我们再让cur向后走到原来Node2的位置,也就是交换后的Node1的位置,即cur = Node1即可完成一轮迭代。
当cur后面没有节点或者cur后面只有一个节点时,说明没有可交换的节点了,所以我们迭代停止的条件就是cur->next == NULL 或cur->next->next == NULL。
最后我们返回新的头节点,也就是dumbNode->next。

2.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

struct ListNode* swapPairs(struct ListNode* head){
    if (NULL == head || NULL == head->next) {
        return head;
    }
    // 创建一个辅助节点
    struct ListNode dumbNode = { 0 };
    dumbNode.next = head;
    struct ListNode *cur = &dumbNode;
    struct ListNode *Node1 = NULL;
    struct ListNode *Node2 = NULL;
    while (cur->next && cur->next->next) {
        Node1 = cur->next;
        Node2 = Node1->next;
        
        // 两两交换
        cur->next = Node2;
        Node1->next = Node2->next;
        Node2->next = Node1;

        cur = Node1;
    }
    return dumbNode.next;
    
}

3、方法3——交替的尾插

3.1、思路分析

通过分析题目所给的示例,我们可以看出题目其实是让我们以每两个节点为一组进行位置的交换:
在这里插入图片描述
所以这其实也是在要求我们将两个相邻的奇偶次序的节点进行位置交换。
所以我们就可以针对这一点来设计出一个更加简单易懂的解法:
首先我们还是需要一个cur指针来帮助我们遍历链表,又因为涉及到插入新链表的操作,可能会对cur的next做更改,所以我们还需要一个next指针指向cur的下一个节点,方便插入后能找到cur的下一个节点:
在这里插入图片描述
同时我们还需要一个变量len来记录当前已遍历到的链表的长度,当len为奇数时,我们就将cur尾插到新链表的末尾。当len为偶数时,我们就将cur插入到新链表的倒数第一和倒数第二个节点之间。所以对于新链表我们需要两个指针pre和tail分别记录新链表的倒数第二和倒数第一个节点:
在这里插入图片描述
并且在所有节点都插入完后一定要记得将tail的next置为NULL,因为如果链表的长度是偶数的话,当我们把原链表的倒数第二个节点尾插到新链表中后,该节点的next其实还是指向原链表的最后一个节点的:
在这里插入图片描述

所以当我们把最后一个节点也插入到新链表中时,就会形成一个环:
在这里插入图片描述
这也正是代码会超时的原因。

3.2、代码实现

有了以上思路,那我们写起代码来也就水到渠成了:

struct ListNode* swapPairs(struct ListNode* head){
    if (NULL == head) {
        return NULL;
    }
    struct ListNode *newhead = NULL;
    struct ListNode *cur = head;
    struct ListNode *next = NULL; // 记录从cur的下一个节点,方便cur往后走
    struct ListNode *tail = newhead; // 记录新链表的尾节点
    struct ListNode *pre = newhead; // 记录新链表的尾节点的前一个节点
    int len = 0; // 记录链表的长度
    while (cur) {
        len++;
        next = cur->next;
        if (len % 2 == 1) { 
            // 如果len是奇数,就尾插到链表的最后
            if (NULL == newhead) {
                newhead = cur;
                tail = cur;
                pre = newhead; // 更新pre
            } else {
                tail->next = cur;
                tail = tail->next;
            }
            if (len >= 3) {
                pre = pre->next;
            }
        } else {
            // 如果len是偶数,那就插入到pre和tail之间
            if (pre == newhead) {
                cur->next = newhead;
                newhead = cur;
                pre = newhead; // 更新pre
            } else {
                cur->next = tail;
                pre->next = cur;
                pre = pre->next;
            }
        }
        cur = next;
    }
    tail->next = NULL;
    return newhead;
}

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

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

相关文章

人群计数经典方法Density Map Estimation,密度图估计

&#xff08;3&#xff09;Density Map Estimation&#xff08;主流&#xff09; 这是crowd counting的主流方法 传统方法不好在哪里&#xff1f;object detection-based method和regression-based method无法从图像中提取更抽象的有助于完成人群计数任务的语义特征 概况&…

asp.net个人信息管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net个人信息管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言 开发 asp.net个人信息管理系统VS开发s…

第七章 单行函数

MySQL系列文章目录 http://t.csdn.cn/YTPe9 文章目录 MySQL系列文章目录前言一、函数的理解1、 什么是函数2 、不同DBMS函数的差异3 、MySQL的内置函数及分类 二、 数值函数1 、基本函数2、 角度与弧度互换函数3、 三角函数4、 指数与对数5、进制间的转换 三、字符串函数四、日…

音视频八股文(8)-- h264 AnnexB

NALU(Network Abstract Layer Unit) ⾳视频编码在流媒体和⽹络领域占有重要地位&#xff1b;流媒体编解码流程⼤致如下图所示&#xff1a; H264简介 H.264从1999年开始&#xff0c;到2003年形成草案&#xff0c;最后在2007年定稿有待核实。在ITU的标准⾥称为H.264&#xff0c…

Docker快速创建一个单机版的Jenkins实例

目录 一、创建 Jenkins 实例 二、Pipeline 项目 三、总结 谈到 CI/CD&#xff0c;那便少不了这里面的佼佼者 Jenkins&#xff0c;正如 Jenkins 官网说的一样&#xff1a;“Build great things at any scale”&#xff0c;构建伟大&#xff0c;无所不能&#xff01; 话不多说…

常用传感器-温湿度传感器SHT30

SHT30温湿度传感器 基本信息 工作电压&#xff1a;2.4V-5.5V 通讯协议&#xff1a;IIC 湿度测量范围&#xff1a;0-100 温度测量范围&#xff1a;-40-125 引脚 VIN&#xff1a;电源正极GND&#xff1a;电源负极SCL&#xff1a;数据线SDA&#xff1a;数据线 操作 1.加载库…

digiKam 8.0发布,带来了许多新的功能和改进

导读digiKam 8.0开源、跨平台、免费的专业照片管理软件现在可以下载&#xff0c;这是一个重大更新&#xff0c;带来了许多新的功能和改进。 digiKam 8.0最大的变化是&#xff0c;该软件被移植到最新的Qt 6开源应用框架&#xff0c;以获得更现代和面向未来的体验。然而&#xff…

MATLAB矩阵运算

文章目录 前言一、矩阵的输入与结构操作1-1 矩阵输入1-2 矩阵扩充&#xff08;1&#xff09;扩充行&#xff08;2&#xff09;扩充列&#xff08;3&#xff09;其他命令&#xff08;4&#xff09;矩阵的修改和元素的删除 1-3 特殊矩阵生成 二、矩阵的计算2-1 、矩阵的基本运算2…

详解时间复杂度和空间复杂度问题

前言&#xff1a;本来我并不认为时间复杂度和空间复杂的有多重要&#xff0c;只要日常会判断和分析算法的复杂度即可&#xff0c;但是&#xff0c;不论是在考研的数据结构与算法中&#xff0c;还是在日常的刷题中&#xff0c;我们都会见到&#xff0c;限制我们时间和空间复杂度…

RK3588平台开发系列讲解(进程篇)Linux中进程的一生

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、Linux 系统中进程的一生二、Linux 系统中的进程树三、Linux 进程的分类四、进程优先级五、进程系统调用沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 Linux 进程的相关知识。 一、Linux 系统…

vscode开发wdk

findwdk https://github.com/SergiusTheBest/FindWDK.git 拷贝FindWdk.cmake模块到下面路径中 CMake\share\cmake-3.22\Modules 注意定义系统变量或者修改下面路径&#xff0c;确保能找到wdk工具路径 构建项目 cmake中构建项目通过wdk_add_driver实现 wdk_add_driver(simp…

深度学习训练营之彩色图片分类2

深度学习训练营之彩色图片分类 原文链接环境介绍前置工作设置GPU 导入数据数据查看 构建CNN网络CNN网络的简单介绍代码 进行编译模型训练正式训练 结果可视化使用准确度和损失值进行结果的优良进行分析 原文链接 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习…

【源码解析】SpringBoot日志系统源码分析

LoggingApplicationListener 日志组件的处理是LoggingApplicationListener实现的。LoggingApplicationListener#onApplicationEvent&#xff0c;监听事件。如果实现接口GenericApplicationListener&#xff0c;可以允许适配事件类型。 private static final Class<?>[]…

升级OpenAi/ChatGPT为收费账号绑定API全过程

前言 自从4月1日开始&#xff0c;第一批用户的API就已经过期了&#xff0c;大家可能重新注册新的账号来免费获取ChatGPT/OpenAi的API额度&#xff0c;需要没有18美元额度&#xff0c;但5美元也能调用不少了&#xff0c;一个账号不够&#xff0c;两个&#xff0c;三个&#xff…

NetSuite 负库存控制功能包

目录 1. 前言 2. 功能说明 2.1概述 2.2控制逻辑说明 3. 安装 4. 设置 4.1角色设置 4.2参数设置 4.3负库存追踪记录设置 5. 视频链接 1. 前言 在NetSuite的项目实践中&#xff0c;NetSuite既有功能未能解决用户所面临的负库存问题。参看NetSuite知识会的前期文章&…

《Netty》从零开始学netty源码(四十六)之PooledByteBuf

PooledByteBuf Netty中一大块内存块PoolChunk默认大小为4MB&#xff0c;为了尽可能充分利用内存会将它切成很多块PooledByteBuf&#xff0c;PooledByteBuf的类关系图如下&#xff1a; PooledUnsafeDirectByteBuf与PooledUnsafeHeapByteBuf直接暴露对象的底层地址。 PooledByt…

连续三年增长,徐福记为什么越战越勇?

30年&#xff0c;一个零食品牌能发生什么变化&#xff1f;对徐福记来说&#xff0c;这是一场漫长的拉力赛。 这个过程&#xff0c;是研究消费者喜好变迁的过程&#xff0c;是孜孜不倦创新原料、产品、生产工艺和先进技术的过程&#xff0c;更是徐福记证明自身品牌价值的过程—…

Nero Platinum Suite 2023 白金套装DVD刻录软件 -您强大的无忧包

为什么选择 Nero Platinum&#xff1f; 相信市场领导者&#xff1a;使用这7个搭配和谐的程序&#xff0c;您可以轻松应对多媒体日常。Nero Platinum Suite – 您强大的无忧包 最佳准备 超过 200 种功能为每一项多媒体应用提供解决方案。技术上始终处于最新状态 品质卓越 针…

大数据技术ELK实时检索

一 elasticsearch简介 ElasticSearch是一个高性能&#xff0c;基于Lucene的全文检索服务&#xff0c;是一个分布式的Restful风格的搜索和数据分析引擎&#xff0c;也可以作为NoSQL数据库使用。 对Lucene进行了扩展 原型环境和生产环境可无缝切换 能够水平扩展 支持结构化和非结…

医院导诊指示线路图制作平台,智慧医院专业地图服务

随着国家医疗水平不断进步&#xff0c;配套设施设备日渐完善&#xff0c;医院也进行了不同程度的扩建和新建&#xff0c;为满足人们的医疗需求&#xff0c;无论综合大楼、科室、诊室及住院区域都变得宽敞舒适&#xff0c;患者在诊区内经常找不到自己要去的就诊位置&#xff0c;…