【算法-链表2】反转链表 和 两两交换链表节点

今天,带来链表相关算法的讲解。文中不足错漏之处望请斧正!

理论基础点这里


反转链表

1. 思路

链表操作的本质是修改连接关系,本题我们需要反转链表,也就是每次都让当前节点的next指向自己的上一个。而题目给的是单链表,所以我们需要始终记录前一个节点的地址,来满足当前节点被反转的条件;其次,我们当前节点迭代时要按原本顺序迭代。

2. 参考代码

class Solution6 {
public:
    ListNode *reverseList(ListNode *head) {
        // 每次都让当前节点的next指向前一个节点, 迭代时仍然向后迭代
        ListNode *prev = nullptr;
        ListNode *cur = head;
        ListNode *next = nullptr;
        while (cur != nullptr) {
            next = cur->next; // 保存, 等会要覆盖
            cur->next = prev; // 改变链接关系:让当前节点的next指向前一个节点
            prev = cur;
            cur = next; // 迭代时仍然向后迭代
        }
        return prev; // 当cur走到空, prev正好是最后一个节点, 即新的反转链表的头节点
    }
};

两两交换链表节点

1. 思路

像这种需要改变链接关系的场景,我们都可以给上一个虚拟头节点,来保证改变链接关系的逻辑相同。

具体如何交换呢?

在这里插入图片描述

1. 要能找得到

《移除链表元素》中,我们已经谈过,要操作节点1和节点2,我们必须要能找得到节点1和节点2

2. 统一操作逻辑

对单链表来说,当我们要从头开始操作的时候,逻辑和正常的交换不一样,所以我们选择加入虚拟头结点,来统一交换逻辑。操作逻辑是什么呢?如图。

在这里插入图片描述

3. 何时结束交换?

我们给一个cur,一开始指向dummyHead,它来操作后两个节点。

前提是后面还有两个节点可以操作,所以当cur->next != nullptr && cur->next->next != nullptr的时候我们可以进行操作,反之结束。

这里是有细节的:

  1. cur不可能为空,因为我们给他初始化为dummyHead
  2. cur→next的判断必须放在前面,因为表达式是从左到右判断,如果cur→next→next的判断放在前面,当cur→next==nullptr,对cur→next→next的判断就对空指针解引用了

4. 改变链接需谨慎

修改节点间的链接关系,很容易丢失节点或陷入死循环。

在这里插入图片描述

如上图,要交换1和2,操作应该是:

  1. cur指向2
  2. 2指向1
  3. 1指向3

对应代码就是

  1. cur->next = cur->next->next

这里其实已经出问题了!cur->next被修改,代表1是丢失了。后续我们还需要让1指向3,找不到1了就没法玩。

同理,直接让2指向1以后,3也丢失了,1和3都找不到了。怎么办?

我们可以提前保存,直接把1、2、3保存为node1、node2、node3。

也可以不保存节点2,因为cur指向2后,2是可以找到的,但我们这样写可读性高点。

最后,cur应该怎么迭代呢?

在这里插入图片描述

应该移动两位。

2. 参考代码

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *dummy = new ListNode(-1, head);
        ListNode *cur = dummy;

        while (cur->next && cur->next->next) { // 后面还有两个节点才能交换
            ListNode *node1 = cur->next;
            ListNode *node2 = cur->next->next;
            ListNode *node3 = cur->next->next->next;

            cur->next = node2; // cur->node2
            node2->next = node1; // node2->node1
            node1->next = node3; // node1->node3

            cur = cur->next->next; // 移动2位
        }

        head = dummy->next;
        delete dummy;
        dummy = nullptr;
        return head;        
    }
};

今天的分享就到这里了,感谢您能看到这里。

这里是培根的blog,期待与你共同进步!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端

【React-Native开发3D应用】React Native加载GLB格式3D模型并打包至Android手机端 【加载3D模型】**React Native上如何加载glb格式的模型**第零步,选择相关模型第一步,导入相关模型加载库第二步,自定义GLB模型加载钩子第三步,借助…

Modbus通讯模拟仿真环境的搭建

文章目录 一、概要二、所需工具介绍三、搭建虚拟仿真环境1.Modbus RTU虚拟仿真环境搭建1.1.虚拟串口工具(VSPD)使用1.2.虚拟从站工具(ModSim32)使用1.3.虚拟主站工具(Modscan32)使用1.4.更改虚拟从站工具&a…

【算法】第二代遗传算法NSGA-II优化SVR超参数模型

NSGA-II介绍 NSGA-II(Non-dominated Sorting Genetic Algorithm II)是一种多目标优化算法,用于解决具有多个冲突目标的优化问题。它通过模拟进化过程中的自然选择和遗传操作,逐步改进种群中的解,以找到一组尽可能好的解…

Halcon的 Filter (过滤)目录之add_Image算子

Halcon两个图像相加可以应用在图像融合的场景中。通过将两幅图像的亮度信息相加,可以生成一幅新的图像,使得图像的细节更加清晰,提高目标检测和识别的准确率。例如,在红外图像和可见光图像融合中,加法运算可以将两幅图…

Linux程序设计shell程序学习

目录 1、编写shell脚本,通过循环的形式在终端上打印出等腰梯形 2、编写一个bash脚本程序,用for循环实现将当前目录下的所有.c文件移到指定的目录下,最后在显示器上显示指定目录下的文件和目录。 3、自行编写 shell 脚本,实现从…

【JAVA学习笔记】66 - 本章作业(IO流)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter19/src/com/yinhai/homework 1.使用File类和FileWriter类 (1)在判断e盘下是否有文件夹mytemp,如果没有就创建mytemp public class Homework01 {public static void main(String…

小程序游戏对接广告收益微信小游戏抖音游戏软件

小程序游戏对接广告是一种常见的游戏开发模式,开发者可以通过在游戏中嵌入广告来获取收益。以下是一些与小程序游戏对接广告收益相关的关键信息: 小程序游戏广告平台选择: 选择适合你的小程序游戏的广告平台非常重要。不同的平台提供不同类型…

塔望食研院|骆驼奶市场规模庞大,百亿体量,品牌升级!

自2022年12月塔望咨询开设塔望食品大健康行业与消费研究院(简称塔望食研院)栏目以来,塔望食研院以“为食品行业品牌高质量发展赋能”为理念,不断发布食品大健康行业研究、消费研究报告。塔望食研院致力于结合消费调研数据、企业数…

智能井盖传感器功能,万宾科技产品介绍

在国家治理方面,对社会的治理是一个重要的领域,一定要在推进社会治理现代化过程中提高市政府的管理和工作能力,推动社会拥有稳定有序的发展。在管理过程中对全市井盖进行统一化管理,可能是市政府比较头疼的难题,如果想…

SpringBoot进制转换规则问题

1.填写yml文件 dataSource:driver-class-name: com.mysql.jdbc.Driver789password: 01272.测试类 package com.forever;import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.Spri…

kubernetes-调度

目录 一、k8s调度简介 二、影响kubernetes调度的因素 1、nodename 2、nodeselector 3、亲和与反亲和 (1)nodeaffinity (2)podaffinity(亲和) (3)podantiaffinity&#xff0…

AI系统源码ChatGPT网站源码+ai绘画系统/支持GPT4.0/支持Midjourney局部编辑重绘

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

Python异步编程入门

文章目录 异步编程概念asyncio模块基础event loop和coroutineasync与await关键字代码示例结论在现代软件开发中,异步编程已经成为一个不可或缺的概念,尤其是在处理I/O密集型任务和高并发需求时。Python作为一门多范式编程语言,自3.5版本以来,通过引入asyncio模块和async/aw…

SPASS-图表的创建编辑

点击折线图 展示图如下: 双击图表,可进行编辑 图表基本设定 选择、移动图表元素和调整图表元素的大小 鼠标点击图表元素选择Tab键进行轮换选择Ctrl键鼠标进行多个元素选择十字箭头——移动元素双头箭头——调整元素大小 更改图表的外观 文本的内容、…

番外篇:Linux中好玩的指令(Ubuntu环境)

前言 我知道,Linux的学习总是枯燥乏味的,今天给大家带来一些好玩的指令,供大家娱乐开心,整理不易,希望大家能够多多支持一下。 1. lolcat指令 输入以下命令即可安装lolcat: sudo apt-get install lolcat 安…

洛谷 P1020 [NOIP1999 普及组] 导弹拦截【一题掌握三种方法:动态规划+贪心+二分】最长上升子序列LIS解法详解

P1020 [NOIP1999 普及组] 导弹拦截 前言题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题目分析注意事项 代码动态规划(NOIP要求:时间复杂度O(n^2^))贪心二分(O(nlgn)) 后话额外测试用例样例输入 #1…

微服务-grpc

微服务 一、微服务(microservices) 近几年,微服这个词闯入了我们的视线范围。在百度与谷歌中随便搜一搜也有几千万条的结果。那么,什么是微服务 呢?微服务的概念是怎么产生的呢? 我们就来了解一下Go语言与微服务的千丝…

Java设计模式之迭代器模式

定义 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 结构 迭代器模式主要包含以下角色: 抽象聚合角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。具体聚合角色:实现抽象聚合类&a…

电机控制::理论分析::延迟环节对系统的影响

控制工程与理论 - 知乎 (zhihu.com) 浅论控制器的增益大小 (上) - 知乎 (zhihu.com) 浅论控制器的增益大小 (下) - 知乎 (zhihu.com) 延迟环节对控制系统的影响_延时环节的传递函数-CSDN博客

2023年双11有哪些便宜的云服务器值得推荐?

每年的双11期间各大云计算服务商都会推出特价云服务器,今年自然也不例外,下面给大家分享2023年双11有哪些便宜的云服务器值得推荐。 1、阿里云【传送门>>>】 阿里云双11推出了金秋云创季活动,2核2G3M不限流量,1年99元&…