【数据结构-链表-01】反转链表

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

      • 反转链表-力扣 206 题
        • 1.解法一
        • 2.解法二
        • 3.解法三
        • 4.解法四
        • 5.解法五
        • 6.解法六

反转链表-力扣 206 题

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

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

1.解法一

题解:

class Solution:def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:"""反转链表:定义前节点和当前节点:param head::return:"""pre, curr = None, headwhile curr is not None:next = curr.nextcurr.next = prepre = currcurr = nextreturn pre

2.解法二

构造一个新链表,从旧链表依次拿到每个节点,创建新节点添加至新链表头部,完成后新链表即是倒序的

评价:简单直白,就是得新创建节点对象

// 创建新节点
public ListNode reverseList(ListNode o1) {//创建新的链表空节点ListNode n1 = null;//设置临时节点,把o1指向pListNode p = o1;while (p != null) {//创建节点,新节点的下一个节点是新链表,并重置新链表的头部n1 = new ListNode(p.val, n1);//移动旧链表的位置p = p.next;}//因为重置了n1,直接返回n1return n1;
}

3.解法三

与方法 2 类似,构造一个新链表,从旧链表头部移除节点,添加到新链表头部,完成后新链表即是倒序的,区别在于原题目未提供节点外层的容器类,这里提供一个,另外一个区别是并不去构造新节点

评价:更加面向对象,如果实际写代码而非刷题,更多会这么做

// 设计一个List
public ListNode reverseList(ListNode head) {//旧链表List o1 = new List(head);//新链表List n1 = new List(null);while (true) {//不断取旧链表的第一个元素final ListNode listNode = o1.removeFirst();//如果旧链表为空,则跳出循环if (listNode == null) {break;}//将旧链表的第一个元素添加到新链表的头部n1.addFirst(listNode);}return n1.head;
}static class List {ListNode head;public List(ListNode head) {this.head = head;}/*** 添加到头节点** @param first*/public void addFirst(ListNode first) {//头节点的下一个节点是headfirst.next = head;//重置headhead = first;}/*** 删除头节点** @return*/public ListNode removeFirst() {//此时的head是旧链表的head,需要截断头节点,并返回完整的节点ListNode first = head;if (first != null) {head = first.next;}return first;}
}

4.解法四

递归,在递归时让 5 → 4 5 \rightarrow 4 54 4 → 3 4 \rightarrow 3 43

首先,写一个递归方法,返回值用来拿到最后一个节点

  • 注意 1:递归终止条件是 curr.next == null,目的是到最后一个节点就结束递归,与之前递归遍历不一样
  • 注意 2:需要考虑空链表即 p == null 的情况

下面为伪码调用过程,假设节点分别是 1 → 2 → 3 → 4 → 5 → n u l l 1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 12345null,先忽略返回值

reverseList(ListNode p = 1) {reverseList(ListNode p = 2) {reverseList(ListNode p = 3) {reverseList(ListNode p = 4) {reverseList(ListNode p = 5) {if (p == null || p.next == null) {return p; // 返回5}}// 此时p是4, p.next是5}// 此时p是3, p.next是4}// 此时p是2, p.next是3}// 此时p是1, p.next是2
}

接下来,从 p = 4 开始,要让 5 → 4 5 \rightarrow 4 54 4 → 3 4 \rightarrow 3 43

reverseList(ListNode p = 1) {reverseList(ListNode p = 2) {reverseList(ListNode p = 3) {reverseList(ListNode p = 4) {reverseList(ListNode p = 5) {if (p == null || p.next == null) {return p; // 返回5}}// 此时p是4, p.next是5, 要让5指向4,代码写成 p.next.next=p// 还要注意4要指向 null, 否则就死链了}// 此时p是3, p.next是4}// 此时p是2, p.next是3}// 此时p是1, p.next是2
}

最终解法

//递归
public ListNode reverseList(ListNode p) {if (p == null || p.next == null) {return p; // 最后节点}ListNode last = reverseList(p.next);//这里最后一个节点是倒数第二个节点p.next.next = p;//防止死循环,环形链表p.next = null;return last;
}

5.解法五

从链表每次拿到第二个节点,将其从链表断开,插入头部,直至它为 null 结束

  1. 设置指针 o1(旧头)、n1(新头)、o2(旧老二),分别指向第一,第一,第二节点

n 1 o 1 1 → o 2 2 → 3 → 4 → 5 → n u l l \frac{n1 \ o1}{1} \rightarrow \frac{o2}{2} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 1n1 o12o2345null

  1. 将 o2 节点从链表断开,即 o1 节点指向第三节点

$ \frac{n1 \ o1}{1} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null$ , o 2 2 \frac{o2}{2} 2o2

  1. o2 节点链入链表头部,即

o 2 2 → n 1 o 1 1 → 3 → 4 → 5 → n u l l \frac{o2}{2} \rightarrow \frac{n1 \ o1}{1} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 2o21n1 o1345null

  1. n1 指向 o2

n 1 o 2 2 → o 1 1 → 3 → 4 → 5 → n u l l \frac{n1 \ o2}{2} \rightarrow \frac{o1}{1} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 2n1 o21o1345null

  1. o2 指向 o1 的下一个节点,即

n 1 2 → o 1 1 → o 2 3 → 4 → 5 → n u l l \frac{n1}{2} \rightarrow \frac{o1}{1} \rightarrow \frac{o2}{3} \rightarrow 4 \rightarrow 5 \rightarrow null 2n11o13o245null

  1. 重复以上 2 ∼ 5 2\sim5 25 步,直到 o2 指向 null

  2. 还应当考虑边界条件,即链表中不满两个元素时,无需走以上逻辑

/*** 不断把 o2 头插入 n1** @param o1* @return*/
public ListNode reverseList(ListNode o1) {// 1. 空链表  2. 一个元素if (o1 == null || o1.next == null) {return o1;}ListNode o2 = o1.next;//新链表的指针ListNode n1 = o1;while (o2 != null) {//旧链表移动一位o1.next = o2.next;//取出的数据的下一个节点指向新链表的头结点o2.next = n1;//重置n1n1 = o2;//重置o2o2 = o1.next;}return n1;
}

6.解法六

要点:把链表分成两部分,思路就是不断从链表 2 的头,往链表 1 的头搬移

  1. n1 指向 null,代表新链表一开始没有元素,o1 指向原链表的首节点

n 1 n u l l \frac{n1}{null} nulln1 o 1 1 → 2 → 3 → 4 → 5 → n u l l \frac{o1}{1} \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 1o12345null

  1. 开始循环,o2 指向原链表次节点

n 1 n u l l \frac{n1}{null} nulln1 o 1 1 → o 2 2 → 3 → 4 → 5 → n u l l \frac{o1}{1} \rightarrow \frac{o2}{2} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 1o12o2345null

  1. 搬移

o 1 1 → n 1 n u l l \frac{o1}{1} \rightarrow \frac{n1}{null} 1o1nulln1 o 2 2 → 3 → 4 → 5 → n u l l \frac{o2}{2} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 2o2345null

  1. 指针复位

n 1 1 → n u l l \frac{n1}{1} \rightarrow null 1n1null o 1 o 2 2 → 3 → 4 → 5 → n u l l \frac{o1 \ o2}{2} \rightarrow 3 \rightarrow 4 \rightarrow 5 \rightarrow null 2o1 o2345null

  1. 重复 2 ∼ 4 2\sim4 24
  2. 当 o1 = null 时退出循环
//不断把 o1 头插到 n1
public ListNode reverseList(ListNode o1) {if (o1 == null || o1.next == null) {return o1;}//创建空链表ListNode n1 = null;while (o1 != null) {ListNode o2 = o1.next;//取出节点后指向新节点o1.next = n1;//重置n1n1 = o1;//重置o1o1 = o2;}return n1;
}

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

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

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

相关文章

多个开源姿态检测模型项目,上手即用,实测可行!

编辑:OAK中国 项目来源:oakchina.cn 喜欢的话,请多多👍⭐️✍ ▌前言 Hello,大家好,这里是OAK中国,我是助手君。 我发现今年有不少朋友都想做姿态检测,正好我们也有不少客户做过这…

结构体(个人学习笔记黑马学习)

1、结构体的定义和使用 #include <iostream> using namespace std; #include <string>struct Student {string name;int age;int score; }s3;int main() {//1、struct Student s1;s1.name "张三";s1.age 18;s1.score 100;cout << "姓名&a…

Python中小数据池知识最详细教程

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 话不多说&#xff0c;直接开搞&#xff0c;如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 一、id&#xff0c;is&#xff0c; 在Python中&#xff0c;id是什么&#xff1f; id是内存地址&#xff0c;比如你利用i…

【Unity小技巧】手戳一个简单易用的游戏UI框架(附源码)

文章目录 前言整套框架分为三大部分素材效果框架代码调用源码参考完结 前言 开发一款游戏美术成本是极其高昂的&#xff0c;以我们常见的宣传片CG为例&#xff0c;动辄就要成百上千万的价格&#xff0c;因此这种美术物料一般只会放在核心剧情节点&#xff0c;引爆舆论&#xf…

生产环境部署与协同开发 Git

目录 一、前言——Git概述 1.1 Git是什么 1.2 为什么要使用Git 什么是版本控制系统 1.3 Git和SVN对比 SVN集中式 Git分布式 1.4 Git工作流程 四个工作区域 工作流程 1.5 Git下载安装 1.6 环境配置 设置用户信息 查看配置信息 二、git基础 2.1 本地初始化仓库 ​编辑…

Java 中数据结构LinkedList的用法

LinkList 链表&#xff08;Linked list&#xff09;是一种常见的基础数据结构&#xff0c;是一种线性表&#xff0c;但是并不会按线性的顺序存储数据&#xff0c;而是在每一个节点里存到下一个节点的地址。 链表可分为单向链表和双向链表。 一个单向链表包含两个值: 当前节点…

创新指南|CEO如何应对生成式AI带来的4大颠覆创新机遇

生成式AI是一种快速发展的颠覆式创新&#xff0c;可以帮助企业创新商业模式、提高效率和解锁商业价值。本研究介绍如何应对生成式AI技术带来的挑战和机遇&#xff0c;以及如何先发利用这种技术来超越竞争和组织创造力和效率。如果您想了解更多关于生成式AI的企业创新战略&#…

【C++深入浅出】初识C++下篇(auto关键字、范围for、nullptr指针)

目录 一. 前言 二. auto关键字 2.1 auto的引入 2.2 auto简介 2.3 auto的使用细则 2.4 auto不能推导的场景 三. 基于范围的for循环(C11) 3.1 范围for的语法 3.2 范围for的原理 3.3 范围for的使用条件 四. 指针空值nullptr(C11) 一. 前言 上期我们介绍了c新增的两个重…

网络基础知识socket编程

目录 网络通信概述网络互连模型&#xff1a;OSI 七层模型TCP/IP 四层/五层模型数据的封装与拆封 IP 地址IP 地址的编址方式IP 地址的分类特殊的IP 地址如何判断2 个IP 地址是否在同一个网段内 TCP/IP 协议TCP 协议TCP 协议的特性TCP 报文格式建立TCP 连接&#xff1a;三次握手关…

服务器端使用django websocket,客户端使用uniapp 请问服务端和客户端群组互发消息的代码怎么写的参考笔记

2023/8/29 19:21:11 服务器端使用django websocket,客户端使用uniapp 请问服务端和客户端群组互发消息的代码怎么写 2023/8/29 19:22:25 在服务器端使用Django WebSocket和客户端使用Uniapp的情况下&#xff0c;以下是代码示例来实现服务器端和客户端之间的群组互发消息。 …

前端加springboot实现Web Socket连接通讯以及测试流程(包括后端实现心跳检测)

【2023】前端加springboot实现Web Socket连接通讯&#xff08;包括后端实现心跳检测&#xff09; 前言一、Web Socket 简绍1 为什么用 websocket&#xff1f; 二、代码实现1、前端&#xff08;html&#xff09;1.1、无前端向后端发送消息1.2、有前端向后端发送消息 2、后端具体…

springboot整合jquery实现前后端数据交互

一 实施逻辑 1.1 前端 <!doctype html> <html lang"en"><head><meta charset"UTF-8"><meta name"Generator" content"EditPlus"><meta name"Author" content""><meta n…

C# 生成唯一ID

1.首先通过nuget安装yitter.idgenerator 下面的三行代码搞定

win11 docker-desktop安装记录

win11安装Docker踩坑实录 马上开始正式工作了&#xff0c;需要用到docker&#xff0c;以前在win10上安装过&#xff0c;新电脑是win11&#xff0c;心想肯定会遇到坑&#xff0c;就浅浅记录一下 首先看一下安装要求 需要wsl2 那么就先进行 wsl的更新 wsl --update注意这里网络…

【STM32】串口初步使用

本文只作为学习笔记&#xff0c;对串口进行一个简单的介绍&#xff0c;正确的使用方式还需要进行实际的调试 通信的类型&#xff1a; 同步 异步 单工 双工 串行 并行 STM32的串口通信&#xff1a; 配置片上外设的控制寄存器&#xff0c;通信双方进行相同的配置&#xff0c;…

VScode代码自动补全提示

VScode代码自动补全提示 打开设置 搜索 Suggest:Snippets Prevent Quick Suggestions &#xff0c;去掉勾选 CtrlShiftP打开setting.json文件&#xff0c;添加以下代码 "editor.suggest.snippetsPreventQuickSuggestions": false,"editor.quickSuggestions…

C++标准库STL容器详解

目录 C标准模板库STL容器容器分类容器通用接口 顺序容器vectorlistdeque 容器适配器queuestackpriority_queue 关联容器&#xff1a;红黑树setmultisetmapmultimap 关联容器&#xff1a;哈希表unordered_set和unordered_multisetunordered_map和unordered_multimap 附1&#xf…

数据库集群的简单了解

Update 关于操作的日志 1.0 redo log 读一次写一次 一共2次, 不安全 注意redo log是顺写 而file是随机 所以Mysql做出类似HDFS的操作 行为日志和数据分离&#xff0c;但是不同的是&#xff0c;Mysql在内存中操作修改&#xff0c;如果不出事故&#xff0c;由内存中的行为来直接…

ES 7.6 - JAVA应用基础操作篇

ES 7.6 - JAVA应用基础操作篇 环境准备依赖配置 实体类准备使用说明索引/映射操作创建索引和映射索引和映射相关查询删除索引 文档操作插入数据更新数据删除数据批量操作 文档查询根据ID查询根据字段精准查询根据字段分词查询控制返回字段范围查询组合查询排序分页高亮搜索聚合…

装备一台ubuntu

配置远程连接&#xff1a; ubuntu的root用户无法远程登入问题&#xff1a; openssh安装命令&#xff1a; sudo apt-get install openssh-server 安装完成通过以下命令查看SSH是否启动 ps -e | grep ssh 如果只有ssh-agent表示还没启动&#xff0c;需要&#xff1a; /etc/i…