题目:反转列表

news2024/11/30 7:41:15

目录

一、题目描述

方法一:扭动箭头

思路:

注意点:

代码:

代码解析:

1.

2.

优化代码:

注意:

1.

2.

方法二:头插

1.介绍头插

2.解决思路

3.代码

4.注意点

总结:

需要注意的是:


一、题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

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

示例 3:

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

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

方法一:扭动箭头

思路:

通过三个指针prev 、 next 、 cur。利用cur遍历节点,实现指针箭头的转向。

其中prev和cur用来反转,next用来迭代!

注意点:

1.需要注意的是,利用了指向第三个节点的指针next,因此要保证至少有两个节点。

注意题目中给出的范围,当只有一个或者两个节点的时候,直接返回即可。

2.做链表题,一定要注意链表的头、尾节点。next == null时,代表cur指针到达了尾节点。

代码:


struct ListNode* reverseList(struct ListNode* head) {
    
    if(head == NULL)
        return head;
    struct ListNode* prev = head;
    struct ListNode*cur = head->next;   
    if(cur == NULL)
        return head;
    struct ListNode* next = cur->next;  //既然指向第三个节点的指针,则一定要考虑只有一个节点或者没有节点的情况!
    prev->next = NULL;

    while(cur)
    {
        if(next == NULL){
            cur->next = prev;
            break;
        }

        else{      
            cur->next = prev;
        }

        prev = cur;          
        cur = next;
        next = cur->next;
    }

    return cur;

}

代码解析:

1.

if(head == NULL)        //没有元素

        return head;

if(cur == NULL)        //只有一个元素

        return head;

对于内存、野指针问题,在链表中一定要十分谨慎!

2.

if(next == NULL){

            cur->next = prev;

            break;

        }

        else{      

            cur->next = prev;

        }

        prev = cur;          

        cur = next;

        next = cur->next;

可以观察到,当遍历节点的时候,if和else语句只需要完成指针的指向改变功能即可。

其余的语句可以封装在外部,作为循环的控制条件。

对于循环之中的迭代,往往位于外部,控制循环的运行。if语句的内部用来进行功能的实现。

优化代码:

直接让prev本身就是空

struct ListNode* reverseList(struct ListNode* head) {
    
    if(head == NULL)
        return head;
    struct ListNode* prev = NULL;
    struct ListNode* cur = head;   
    struct ListNode* next = cur->next;  

    while(cur)
    {
        cur->next = prev;

        prev = cur;
        cur = next;
        if(next)
            next = next->next;
    }
    return prev;

}

解析:cur正常后移(不断追赶next)。

当next为空时,next不在后移,cur后移追赶next到空,循环结束。

注意:

1.

链表题目!!!一定要对代码的整体逻辑的先后顺序理清楚!!!

如:此代码

先改变指向,prev追cur,再cur追赶next,再next后移。

当对整体逻辑理清楚之后,代码变得更加简洁。

2.

当存在三个指针的时候,尝试利用画图,对初始指针(如prev)进行节点的位移,会使代码更简洁。

方法二:头插

1.介绍头插

头插即头部插入


void SLPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);  // 链表为空,pphead也不为空,因为他是头指针plist的地址		//pphead 要断言 , 因为需要对 pphead 进行解引用操作并修改 *pphead  =  ....
	//assert(*pphead); // 不能断言,	链表为空,也需要能插入	//因为 *pphead 不需要再次解引

	SLTNode* newnode = BuyLTNode(x);

	newnode->next = *pphead;	//为空可以插入
	*pphead = newnode;		//新头指向最开头的节点
}

2.解决思路

取一个新指针newhead,去引领一个新的地址。利用头插,取原链表的节点,插入到头部。

3.代码

struct ListNode* reverseList(struct ListNode* head) {

       

    struct ListNode* newhead = NULL;

    struct ListNode* cur = head;

   

    if(head == NULL)

        return NULL;



    struct ListNode* next = head->next; //需要十分敏感!当需要用到next此类的指针的时候,一定要警惕cur是不是空指针!



        while(cur)

        {

            cur->next = newhead;

            newhead = cur;

            // cur = cur->next;                 //不对,cur->next是空!

            cur = next;

            if(next)

                next = next->next;

        }




    return newhead;    

}

4.注意点

1.struct ListNode* next = head->next;         //需要十分敏感!当需要用到next此类的指针的时候,一定要警惕cur是不是空指针,防止出现野指针!!!

2.   // cur = cur->next;         //不对,cur->next是空!

由于第一步中已经将cur指向newhead,所以cur的next是空!

画图时,需要对原链表和newhead进行同时标注cur位置!

3.if(next)

最后一步next不能后移,否则会出现野指针!

总结:

方法一:需要利用prev 、 cur 、 next三个指针,来进行箭头逆置(cur指向prev)迭代(cur、prev、next不断往下遍历)

方法二:需要利用头插的思想完成每个节点的插入。

方法一和方法二,都是从原节点头部开始取节点,依次往下进行!

需要注意的是:

对于链表的题目,头插和尾插的思想十分常见。当头插行不通时,常常考虑尾插;尾插行不通,常常考虑头插。

头插:取新节点,利用头插的方式,插入到newhead的头部。常用到newhead。

尾插:取新节点,利用尾插的方式,插入到newhead链表的尾部。常用到newhead。

无论头插还是尾插,对于单链表而言,都是需要从原链表的开头位置开始取节点。(源节点的链接顺序是从头链接至尾,而不是从尾链接至头)

对于尾插,若想详细了解,见下方博客

用尾插的思路实现 “合并两个有序链表”-CSDN博客

用尾插的思想实现移除链表中的元素-CSDN博客(推荐

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

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

相关文章

AV1:帧内预测(一)

​VP9支持10种帧内预测模式&#xff0c;包括8种角度模式和非角度模式DC、TM(True Motion)模式&#xff0c;AV1在其基础上进一步扩展&#xff0c;AV1帧内预测角度模式更细化&#xff0c;同时新增了部分非角度模式。 扩展的角度模式 AV1在VP9角度模式的基础上进一步扩展&#xf…

漫谈微服务网关

一、什么是服务网关 服务网关 路由转发 过滤器 1、路由转发&#xff1a;接收一切外界请求&#xff0c;转发到后端的微服务上去&#xff1b; 2、过滤器&#xff1a;在服务网关中可以完成一系列的横切功能&#xff0c;例如权限校验、限流以及监控等&#xff0c;这些都可以通过…

AI智能客服的数据训练流程

实现智能客服的数据训练流程可以分为几个主要步骤&#xff0c;包括数据准备、模型选择、模型训练和评估。以下是一个基本的数据训练流程&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.数据准备&am…

软件开发项目管理/研发项目管理软件:国产EDA工具厂商行芯科技上线奥博思PowerProject项目管理软件平台

国内领先的EDA工具链提供商杭州行芯科技有限公司&#xff08;以下简称&#xff1a;行芯科技&#xff09;与北京奥博思软件技术有限公司达成战略合作&#xff0c;奥博思软件将基于PowerProject项目管理系统助力行芯科技实现研发项目的全生命周期管理&#xff0c;提升管理效能&am…

fastjson反序列化攻略

漏洞原理 Json.parseObject(json, User.class)方法中&#xff0c;通过指定type的值实现定位某类&#xff0c;会执行User类的构造方法和属性中的get&#xff0c;set方法 判断是否是fastjson/&#xff08;jackson&#xff09; 1.2.24-1.2.83都会有dnslog的payload {"zer…

基于Springboot的船运物流管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的船运物流管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

(总结)OpenOFDM接收端信号处理流程

Overview — OpenOFDM 1.0 documentation 本篇文章为学习OpenOFDM之后的产出PPT&#xff0c;仅供学习参考。

28-4 文件上传漏洞 - %00和00截断

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、白名单绕过、%00和O0截断 %00和O0截断定义: 在URL中,%00表示ASCII码中的0(零),而ASCII中0作为特殊字符保留,所以当URL中出现%00时就会认为读取已结束。这等同于一个结束…

springboot校服订购系统

摘 要 本文首先实现了校服订购系统设计与实现管理技术的发展随后依照传统的软件开发流程&#xff0c;最先为系统挑选适用的言语和软件开发平台&#xff0c;依据需求分析开展控制模块制做和数据库查询构造设计&#xff0c;随后依据系统整体功能模块的设计&#xff0c;制作系统的…

【c语言篇】每日一题-pta-实验11-2-9 链表逆置

题目如下&#xff1a; 裁判测试程序样例&#xff1a; #include <stdio.h> #include <stdlib.h>struct ListNode {int data;struct ListNode *next; };struct ListNode *createlist(); /*裁判实现&#xff0c;细节不表*/ struct ListNode *reverse( struct ListNod…

SCI一区 | Matlab实现GWO-TCN-BiGRU-Attention灰狼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现GWO-TCN-BiGRU-Attention灰狼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现GWO-TCN-BiGRU-Attention灰狼算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程序…

Transformer的前世今生 day04(ELMO

ELMO 前情回顾 NNLM模型&#xff1a;主要任务是在预测下一个词&#xff0c;副产品是词向量Word2Vec模型&#xff1a;主要任务是生成词向量 CBOW&#xff1a;训练目标是根据上下文预测目标词Skip-gram&#xff1a;训练目标是根据目标词预测上下文词 ELMO模型的流程 针对Wor…

15届蓝桥杯备赛(2)

文章目录 刷题笔记(2)二分查找在排序数组中查找元素的第一个和最后一个位置寻找旋转排序数组中的最小值搜索旋转排序数组 链表反转链表反转链表II 二叉树相同的树对称二叉树平衡二叉树二叉树的右视图验证二叉搜索树二叉树的最近公共祖先二叉搜索树的最近公共祖先二叉树层序遍历…

实现el-table合并列

效果图如下 <el-table :data"atlasDataList" style"width: 100%" :span-method"spanMethod"><el-table-column prop"stationName" label"" width"180" /><el-table-column prop"atlasNumbe…

刷题日记:面试经典 150 题 DAY6

刷题日记&#xff1a;面试经典 150 题 DAY6 392. 判断子序列167. 两数之和 II - 输入有序数组11. 盛最多水的容器15. 三数之和209. 长度最小的子数组 392. 判断子序列 原题链接 392. 判断子序列 双指针&#xff0c;i指向s&#xff0c;j指向t 如果s[i]t[j]&#xff0c;则匹配…

ARM开发板实现24位BMP图片缩放

ARM开发板实现24位BMP图片缩放 一、linux平台bmp图片缩放 最近想在ARM开发板实现BMP图片的缩放&#xff0c;查看了一些资料&#xff0c;大家部分理论知识可参考&#xff1a; akynazh博主 &#xff0c;这位博主程序以window平台为主进行显示&#xff0c;发现在linux平台下编译…

【Leetcode】1793. 好子数组的最大分数

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个整数数组 n u m s nums nums &#xff08;下标从 0 0 0 开始&#xff09;和一个整数 k k k 。 一个子数组 ( i , j ) (i, j) (i,j) 的 分数 定义为 m i n ( n u m s …

Livox激光雷达 mid360 跑 fastlio2 - 流程记录

mid360 跑 fastlio2 一、配置 mid360 环境1.1、主机配置静态IP为192.168.1.501.2、Livox-SDK21.3、Livox_ros_driver2二、Fast-lio22.1、下载源码2.2、修改代码2.3、编译、运行 提示一下&#xff0c;如果在一些板上&#xff08;比如rk3399&#xff0c;或者是树莓派 &#xff0…

蓝桥杯java组 螺旋折线

题目描述 如图所示的螺旋折线经过平面上所有整点恰好一次。 对于整点(X, Y)&#xff0c;我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。 例如dis(0, 1)3, dis(-2, -1)9 给出整点坐标(X, Y)&#xff0c;你能计算出dis(X, Y)吗&#xff1f; 【输入格…

Spring-AOP面相切面编程示例(有详细注释)

前提知识Spring-IOC容器注解方式使用https://blog.csdn.net/m0_61160520/article/details/136784799?spm1001.2014.3001.5501切点表达式https://blog.csdn.net/m0_61160520/article/details/136782885?spm1001.2014.3001.5501 案例 1.创建项目 2.导入依赖 <dependencie…