【LeetCode】链表反转

news2024/11/24 2:58:20

题目

题目:给定单链表头节点,将单链表的链接顺序反转过来
例:
输入:1->2->3->4->5
输出:5->4->3->2->1
要求:按照两种方式实现

解决办法

方式一:(直接迭代法)

思路

单链表的结构如下所示:
在这里插入图片描述
如图所示。我们分析一下,如果要完成翻转需要思考什么:

  1. 循环遍历所有节点,直到结束。所以需要确认结束条件
  2. 安全地将当前节点指向它的前驱节点(直接指向的话会导致链表遍历失败,如下所示,找不到下一个操作节点了)
    在这里插入图片描述

对于第1点,既然要循环遍历,那无非就是迭代器或者循环了,显然这里没办法使用迭代器,所以考虑使用while循环。何时结束呢?不难发现,就是【当前节点的next节点为null的时候】,或者我们新增一个节点currNode,表示当前操作节点,它随着遍历深度,不断往后移。显然它初始值是head头节点,所以可以使用currNode == null表示遍历结束了。
对于第2点,如何才能安全地将当前节点指向它的前驱节点呢?正常来说需要以下2步才能保证:

  1. 记录当前节点原有的next指向节点,这里记录为oldNextNode (原因见上图)
  2. 还需要一个前驱节点preNode记录下一个节点需要设置的前驱节点(也可以看上图,除了找不到next节点以外,其实next节点也找不到前面的节点了,所以也需要记录)

准备好了我们就可以尝试模拟了。
在这里插入图片描述
操作步骤:

  1. 设置oldNextNodecurrNode的next节点
  2. currNode的next节点指向preNode
  3. preNode设置为currNode
  4. currNode设置为oldNextNode
    在这里插入图片描述
    似乎没问题,那我们开始写代码吧

代码示例

代码如下:

public class ReverseLinkedList {
    public static void main(String[] args) {
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

        reverseLinkedList(node1);
    }

    private static void reverseLinkedList(ListNode head) {

        // 初始化我们的中间节点
        ListNode currNode = head;
        ListNode oldNextNode = null;
        ListNode preNode = null;

        // 循环遍历,currNode != null 则表示还没遍历到结尾
        while (currNode != null) {
            oldNextNode = currNode.next;
            currNode.next = preNode;
            preNode = currNode;
            currNode = oldNextNode;
        }

        System.out.println("试试看");
        System.out.println(preNode);
    }
}

最后我们看看结果吧:
在这里插入图片描述
倒过来了!

方式二:(递归法)

思路

(PS:既然说是递归解决了,那我们得先知道,递归能做什么。可以这么说,凡是能用递归解决的问题,一定是能将某个大问题,划分成N个存在共性的小问题。所以,我们可以朝这个方向看看。)

还是看着单链表的结构图来思考:
在这里插入图片描述
我们发现,如果从最后一个节点开始出发的话,这个题目的问题就会变成了另一个问题:我的前驱节点是谁?
在正常的遍历中,我们使用preNode状态节点来记录前驱节点,但在递归里面就没那么麻烦了!因为在正向递归遍历节点的时候,当前节点的结束,肯定是在前驱节点的调用处。效果图如下:
在这里插入图片描述
递归代码如下所示:

    public static void main(String[] args) {
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

//        reverseLinkedList(node1);
        recursion(node1);
    }

    private static ListNode recursion(ListNode curr) {

        // 递归出口(遍历到最后了)
        if (curr == null || curr.next == null) {
            return curr;
        }

        ListNode recursion = recursion(curr.next);
        System.out.println(recursion.value);
        return curr;
    }
//    系统输出:
//            5
//            4
//            3
//            2

既然知道了这个特点,我们只需要做如下步骤就好了:

  1. 每次递归调用,返回当前节点(这是为了创造当前节点能跟前驱节点在同一个代码块里的环境)
  2. 获得递归调用返回的节点recursion 之后,使用recursion .next = curr; curr.next = null;即可
    在这里插入图片描述

代码示例

   public static void main(String[] args) {
        ListNode node5 = new ListNode(5, null);
        ListNode node4 = new ListNode(4, node5);
        ListNode node3 = new ListNode(3, node4);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(1, node2);

//        reverseLinkedList(node1);
        recursion(node1);
        System.out.println(node5);
    }

    private static ListNode recursion(ListNode curr) {

        // 递归出口(遍历到最后了)
        if (curr == null || curr.next == null) {
            return curr;
        }

        ListNode recursion = recursion(curr.next);
        recursion.next = curr;
        curr.next = null;
        return curr;
    }

最后我们看看结果吧:
在这里插入图片描述

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

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

相关文章

从0开始自学网络安全(黑客)

前言 黑客技能是一项非常复杂和专业的技能,需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤,系统自学网络安全。 在学习之前,要给自己定一个目标或者思考一下要达到一个什么样的水平,是学完找工作(…

这所211考数一英二,学硕降分33分,十分罕见!

一、学校及专业介绍 合肥工业大学(Hefei University of Technology),简称“合工大”,校本部位于安徽省合肥市,是中华人民共和国教育部直属的全国重点大学,是国家“双一流”建设高校, 国家“211工…

PHP代码审计——实操!

ctfshow PHP特性 web93 八进制与小数点 <?php include("flag.php"); highlight_file(__FILE__); if(isset($_GET[num])){$num $_GET[num];if($num4476){die("no no no!");}if(preg_match("/[a-z]/i", $num)){die("no no no!")…

git 忽略掉不需要的文件

第一步&#xff1a;创建.gitignore文件 touch .gitignore 第二步&#xff1a;使用vi编辑器 输入不需要的文件&#xff0c;或用通配符*来忽视一系列文件 效果&#xff1a;

【Java可执行命令】(十二)依赖分析工具jdeps:通过静态分析字节码并提取相关信息来实现依赖分析 ~

Java可执行命令之jdeps 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 jdeps -dotoutput < dir>3.3 jdeps -s3.4 jdeps -v3.5 jdeps -cp < path>3.6 注意事项&#xff1a; 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 Java中的jdeps命令是一个用于分析类…

使用脱机 MFA确保远程员工的安全

远程工作支持的优势 未更改的企业访问&#xff1a;远程工作支持开辟了访问企业网络和资源以及其中保存的数据的替代方法。应采取必要措施&#xff0c;确保它们保持完整&#xff0c;不受远程破坏企图的影响。提高工作效率&#xff1a;理想情况下&#xff0c;远程工作支持可提高…

程序框架-事件中心模块-观察者模式

1.Monster //触发事件 EventCenter.GetInstance().EventTrigger("MonsterDead",this);2.Player void Start() { EventCenter.GetInstance().AddEventListener("MonsterDead", MonsterDeadDo); }public void MonsterDeadDo(object info) {Debug.Log(&q…

【测试开发】Mq消息重复如何测试?

本篇文章主要讲述重复消费的原因&#xff0c;以及如何去测试这个场景&#xff0c;最后也会告诉大家&#xff0c;目前互联网项目关于如何避免重复消费的解决方案。 Mq为什么会有重复消费的问题? Mq 常见的缺点之一就是消息重复消费问题&#xff0c;产生这种问题的原因是什么呢…

从封面开始,打造一个引人注目的视频作品

在如今的互联网时代&#xff0c;短视频已经成为了人们生活中不可或缺的一部分。而一个吸引人的视频封面可以让你的作品更具吸引力&#xff0c;吸引更多观众的点击。那么&#xff0c;如何制作一个令人印象深刻的视频封面呢&#xff1f;下面就让我们揭秘一些实用技巧吧&#xff0…

Chrome 75不支持保存成mhtml的解决方法

在Chrome 75之前&#xff0c;可以设置chrome://flags -> save as mhtml来保存网页为mhtml。 升级新版&#xff0c;发现无法另存为/保存网页为MHTML了。 在网上搜索无果后&#xff0c;只得从chromium项目的commits中查找&#xff0c;原来chrome搞了个"Chrome Flag Owner…

新闻稿发布中,首发来源和转载是什么意思?

一秒推小编告诉您&#xff0c;在新闻稿发布中&#xff0c;首发来源和转载是两个常用的词语&#xff0c;它们有着不同的含义和使用场合。#新闻稿发布# 首发来源指的是原创的、第一次发布该条新闻的媒体或媒体机构。比如&#xff0c;如果一家新闻机构发布了一则新闻稿&#xff0c…

圆圈中最后剩下的数字(约瑟夫环)——剑指 Offer 62

文章目录 题目描述法一 数学递归 题目描述 法一 数学递归 int lastRemaining(int n, int m){return f(n, m);}int f(int n, int m){if(n1){return 0;}int x f(n-1, m);return (mx)%n;}

浅析视频技术与AI智能感知与生鲜供应链的数字化应用

一、行业背景 近年来&#xff0c;我国肉类、水果、蔬菜、水产品、乳品、速冻食品等生鲜市场需求快速增长&#xff0c;营商环境持续改善&#xff0c;推动冷链物流较快发展&#xff0c;但仍面临不少突出瓶颈和痛点难点卡点问题&#xff0c;难以有效满足市场需求。传统生鲜食材供…

【EI/SCOPUS征稿】2023年通信网络与机器学习国际学术会议(CNML 2023)

2023年通信网络与机器学习国际学术会议&#xff08;CNML 2023&#xff09; 2023 International Conference on Communication Networks and Machine Learning 随着数据流量的显著增长&#xff0c;新的通信应用程序不断出现&#xff0c;并产生更多的数据流量&#xff0c;这些数…

单片机外部晶振故障后自动切换内部晶振——以STM32为例

单片机外部晶振故障后自动切换内部晶振——以STM32为例 作者日期版本说明Dog Tao2023.08.02V1.0发布初始版本 文章目录 单片机外部晶振故障后自动切换内部晶振——以STM32为例背景外部晶振与内部振荡器STM32F103时钟系统STM32F407时钟系统 代码实现系统时钟设置流程时钟源检测…

RabbitMQ输出日志配置

参考地址rabbitmq启用日志功能记录消息队列收发情况_rabbitmq开启日志_普通网友的博客-CSDN博客 启用日志插件命令 # 设置用户权限 rabbitmqctl set_user_tags mqtt-user administrator rabbitmqctl set_permissions -p / mqtt-user ".*" ".*" ".*&…

总结动量定理的交易规则

动量定理策略是一种趋势策略&#xff0c;基于周线图中的“三烛台”形态(上涨或下跌)进行交易。Forexclub总结的交易规则如下&#xff1a; 1. 下一个烛台必须比上一个烛台大&#xff0c;以确认趋势存在。 2. 多奇烛台(不带主体的烛台)不考虑在内。 3. 止损设置在序列中第一根蜡…

线性代数 | 机器学习数学基础

前言 线性代数&#xff08;linear algebra&#xff09;是关于向量空间和线性映射的一个数学分支。它包括对线、面和子空间的研究&#xff0c;同时也涉及到所有的向量空间的一般性质。 本文主要介绍机器学习中所用到的线性代数核心基础概念&#xff0c;供读者学习阶段查漏补缺…

AIGC风起,快看能否走出“水逆周期”?

文|琥珀消研社 作者| 石榴 7月28日-31日&#xff0c;终于回归线下的ChinaJoy 2023在上海新国际博览中心举行&#xff0c;不仅吸引了广大二次元爱好者&#xff0c;还有不少互联网大厂的影子&#xff0c;比如腾讯、网易、美团、哔哩哔哩等等。 而在同月快看世界举办的第二届KK…

【BASH】回顾与知识点梳理(六)

【BASH】回顾与知识点梳理 六 六. 管线命令 (pipe)6.1 撷取命令&#xff1a; cut, grepcutgrep 6.2 排序命令&#xff1a; sort, wc, uniqsortuniqwc 6.3 双向重导向&#xff1a; tee6.4 字符转换命令&#xff1a; tr, col, join, paste, expandtrcoljoinpasteexpand 6.5 分区命…