广告
返回顶部
首页 > 资讯 > 操作系统 >【数据结构-链表-01】反转链表
  • 378
分享到

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

算法 2023-08-30 17:08:17 378人浏览 安东尼
摘要

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

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

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

反转链表-力扣 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, head        while curr is not None:            next = curr.next            curr.next = pre            pre = curr            curr = next        return pre

2.解法二

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

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

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

3.解法三

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

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

// 设计一个Listpublic 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;    }        public void addFirst(ListNode first) {        //头节点的下一个节点是head        first.next = head;        //重置head        head = first;    }        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. 还应当考虑边界条件,即链表中不满两个元素时,无需走以上逻辑

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;        //重置n1        n1 = o2;        //重置o2        o2 = o1.next;    }    return n1;}

6.解法六

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

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

n 1 n u l l \frac{n1}{null} nulln1o 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} nulln1o 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} 1o1nulln1o 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 1n1nullo 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 头插到 n1public 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;        //重置n1        n1 = o1;        //重置o1        o1 = o2;    }    return n1;}

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

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

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

img

来源地址:https://blog.csdn.net/qyj19920704/article/details/132581371

--结束END--

本文标题: 【数据结构-链表-01】反转链表

本文链接: https://www.lsjlt.com/news/383326.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 【数据结构-链表-01】反转链表
    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,...
    99+
    2023-08-30
    算法
  • Java数据结构之链表实现(单向、双向链表及链表反转)
    前言 之前学习的顺序表查询非常快,时间复杂度为O(1),但是增删改效率非常低,因为每一次增删改都会元素的移动。可以使用另一种存储方式-链式存储结构。 链表是一种物理存储单元上非连续、...
    99+
    2022-11-12
  • Python数据结构之翻转链表
    翻转一个链表 样例:给出一个链表1->2->3->null,这个翻转后的链表为3->2->1->null 一种比较简单的方法是用“摘除法”。就是先新建一个空节点,然后...
    99+
    2022-06-04
    数据结构 链表 Python
  • Python 数据结构之旋转链表
    题目描述:给定一个链表,旋转链表,使得每个节点向右移动k个位置,其中k是一个非负数 样例:给出链表1->2->3->4->5->null和k=2;返回4->5->...
    99+
    2022-06-04
    数据结构 链表 Python
  • 数据结构——链表(java)
    文章目录 链表1. 基本介绍1.1 定义1.2 链表分类3.不带头非循环单链表CURD4.不带头非循环双向链表CURD 链表 1. 基本介绍 1.1 定义 链表是一种物理存储结构...
    99+
    2023-10-02
    数据结构 链表 java
  • python数据结构之链表
    '''' 链表的实现,单向链表 ''' '''建立节点''' class jd:     def __init__(self,data):         self.data = data         self.next = None...
    99+
    2023-01-31
    数据结构 链表 python
  • 数据结构——链表(python版)
    一、链表简介 链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成,结点可以在运行时动态生成。每个结点包含两部分:数据域与指针域。...
    99+
    2023-08-31
    链表 数据结构 python
  • 反转链表 golang
    反转链表是一个经典的数据结构算法问题,需要在链表上对节点进行操作,将链表反转后返回反转后的头节点。使用golang语言实现反转链表可以有效地展示golang的面向对象和指针操作特性,下面我们来具体讲解一下如何实现反转链表。1.定义链表节点结...
    99+
    2023-05-22
  • java数据结构基础:单链表与双向链表
    目录单链表:实现思路:代码实现:双向链表:实现思路:代码实现:总结单链表: 每个数据是以节点的形式存在的 每个节点分为数据域和指针域 数据域中保存该节点的数据 指针域中保存指向下一个...
    99+
    2022-11-12
  • C语言数据结构之双链表&循环链表&静态链表详解
    目录单链表 VS 双链表双链表双链表的初始化(带头结点)双链表的插入双链表的删除双链表的遍历循环单链表循环双链表循环双链表的初始化循环双链表的插入循环双链表的删除静态链表什么是静态链...
    99+
    2022-11-13
  • JAVA版的数据结构——链表
    目录 1.单向不带头链表 1.1 链表的概念及结构 1.2 代码部分 1.3 完整的全部代码 2. 双向不带头链表 2.1 代码部分 2.2 完整的代码 3. MySingleList与MyLinkedList代码上的区别 4. Link...
    99+
    2023-09-12
    java 数据结构 链表
  • python数据结构之链表(linked
    目录 基础 知识 1.1 链表的基本结构 1.2 节点类和链表节点的定义 1.3 顺序打印和逆序打印 链表的基本操作 2.1 计算链表长度 2.2 从前,后插入数据 2.3 查找与删除 参考 1.基础 知识 1....
    99+
    2023-01-31
    数据结构 链表 python
  • C++数据结构之单链表
    目录单链表结构的定义单链表打印动态申请一个结点单链表尾插单链表尾删单链表头插单链表头删求单链表长度单链表查找单链表在pos位置插入单链表在pos后面位置插入单链表删除pos位置单链表...
    99+
    2022-11-12
  • C++相交链表和反转链表详解
    目录给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。思路给你单链表的头节点 head ,请你反转...
    99+
    2022-11-12
  • Python数据结构与算法之链表,无序链表详解
    目录我们首先来构造节点。节点(Node)的类构建完毕后,接下来我们开始构建整个链表(LinkList)的类。那么我们还需要一个方法来判断链表头的指向。接下来我们构建链表节点的添加方法...
    99+
    2022-11-13
  • Java数据结构之链表详解
    目录一、链表的介绍二、单链表的实现三、双向链表的实现四、循环链表的实现五,链表相关的面试题一、链表的介绍 什么是链表 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑...
    99+
    2022-11-12
  • 关于 Java 的数据结构链表
    目录数据结构关于 Java 的链表1. 删除链表中等于给定值 val 的所有节点2. 反转一个单链表3. 给定一个带有头结点 head 的非空单链表4. 输入一个链表,输出该链表中倒...
    99+
    2022-11-12
  • C++数据结构之链表详解
    目录前言一、删除链表中给定值为key的节点二、反转链表三、返回链表的中间节点四、删除链表的倒数第K个节点五、分割链表六、合并两个有序链表七、删除有序链表中重复节点八、环形链表九、相交...
    99+
    2022-11-12
  • Redis数据结构之链表详解
    目录1 链表和链表节点的结构2 链表相关的API1 链表和链表节点的结构 1.1 节点结构 节点的结构大概长下边这个样子: 那么,把这些节点就连起来就成了这个样子: 1.2 链表...
    99+
    2022-11-12
  • C++数据结构之双向链表
    本文实例为大家分享了C++数据结构之双向链表的具体代码,供大家参考,具体内容如下 #include <iostream> using std::cout; using ...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作