【力扣高频TOP100】由浅入深细讲反转链表(小白也能听懂)

本文介绍了链表的基本概念,包括链表的定义、种类(单链表、双链表和循环链表)、存储方式,以及链表的增删查改操作,特别是重点讲解了如何反转链表。通过实例和代码演示,帮助读者巩固链表的理解和算法应用。
摘要由CSDN通过智能技术生成

👨‍💻 大唐coding个人主页

 🎁 个人专栏《力扣高频刷题宝典》《SQL刷题记录》

既然选择远方,当不负青春,砥砺前行!

目录

引入

一、链表的基础概念

1.1链表是什么

1.2链表的种类

1.3链表的存储方式

二、链表的增删查改

2.1添加节点

2.2删除节点

2.3总结

三、链表实战之反转链表

3.1题目描述

3.2思路

3.3代码示例

3.4类似题目推荐

四、文章结语


引入

大家好,我是大唐,不知道大家在刚上大学的时候初遇链表是否头疼,我还记得我在第一次学习链表的时候,也是被难住了好久,时间一晃好几年过去了,今天借着讲题的部分,再给大家重温一遍链表的基础概念。今天我们来看一道非常经典而且面试高频的题目------力扣TOP100之反转链表。

那么首先第一件事,链表到底是什么,有什么作用呢?

一、链表的基础概念

1.1链表是什么

链表是一种常见的数据结构,我们可以把链表简单理解为一串珠子,其中每颗珠子都代表一个数据元素,而珠子之间的线则代表它们之间的连接关系

而这种连接关系在链表中是通过指针来实现的,每一个节点由两部分组成,一个是数据域data(用来存放数据),一个是指针域next(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

1.2链表的种类

        单链表:这是最简单的链表类型,每个节点只包含一个指向下一个节点的指针。单链表只能从头部开始遍历,不能从尾部开始遍历。如上图所示。

        双链表:双链表中的每个节点都包含两个指针,一个指向前一个节点,一个指向后一个节点。因此,双向链表可以从头部或尾部开始遍历。

        循环链表:循环链表是一种特殊的链表,它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。也就是说,在循环链表中,从一个节点出发,可以沿着指针方向遍历整个链表,最终回到起始节点。

1.3链表的存储方式

链表的存储方式是不连续的,每个节点都包含数据域和指针域两部分,数据域用于存储数据,指针域用于存储下一个节点的地址。因此,链表是由一个个节点组成的,节点之间的连接通过指针来实现。

我们不难想到另外一种结构---数组,数组也是可以用来存储数据增删查改,那么大家知道它和链表的区别在哪里吗?

链表与数组的区别主要有以下几点:

  1. 存储方式链表是动态存储的,可以根据需要动态地分配和释放内存空间,而数组是静态存储的,需要预先分配固定大小的内存空间。
  2. 内存利用率链表的内存利用率通常比数组高,因为链表中的每个节点只需要存储数据和下一个节点的地址,而数组中的每个元素都需要占用相同大小的内存空间,即使有些元素可能并不需要那么多空间。
  3. 访问速度数组的访问速度通常比链表快,因为数组可以通过索引直接访问任意位置的元素,而链表需要从头节点开始逐个遍历才能访问到指定位置的节点。
  4. 插入和删除操作链表在插入和删除节点时比较方便,只需要修改相邻节点的指针即可,而数组在插入和删除元素时可能需要移动大量元素,因此效率较低

这个链表起始节点为2, 终止节点为7, 各个节点分布在内存的不同地址空间上,通过指针串联在一起。

二、链表的增删查改

那么在学习了上面链表的基础概念和定义后,相比大家已经对链表是什么有一定的了解,那么下面我们开始讲重点,也是我们在刷关于链表算法题时必不可少的一点---增删查改

2.1添加节点

我们想要添加节点,比如在C点和D点之间添加一个F点,我们只需要以下几步:

1、C点指针指向F点

2、F点指针指向D点

只需要这两步,即可大功告成,插入成功,恭喜你完成了通过的第一个小章节!

2.2删除节点

跟增加节点上面类似,不过这次只需要一步即可解决!

1、C点指针指向E点,相当于把原来的D点直接隔开了

不过在完成后,如果是C/C++,需要手动释放D点内存,free即可

其他语言例如Java、Python,就有自己的内存回收机制,就不用自己手动释放了

2.3总结

可以看出链表的增添和删除都是O(1)操作,也不会影响到其他节点。
但是要注意,要是删除第五个节点,需要从头节点查找到第四个节点通过next指针进行删除操作,查找的时间复杂度是O(n)。

三、链表实战之反转链表

相信大家在看完前面链表的基础知识和操作后,已经对链表有了一定的了解了,是不是对链表的算法题跃跃欲试呢,那么下面我们就来练练手。

3.1题目描述

反转链表---难度 ⭐⭐⭐

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

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

3.2思路

如果再定义一个新的链表,就可以实现链表元素的反转来完成本题,但是其实这是对内存空间的浪费。我们在思考一下,如果只改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表,是不是也可以实现呢?如下图所示:

之前链表的头节点是元素1, 反转之后头结点就是元素5 ,这里并没有添加或者删除节点,仅仅是改变next指针的方向。那么接下来看一看是如何反转的呢?

这里借鉴一下别人的动图,如下图所示:

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。

接下来,就是循环,继续移动pre和cur指针。
最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。代码如下:

3.3代码示例

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        cur, pre = head, None
        while cur:
            tmp = cur.next # 暂存后继节点 cur.next
            cur.next = pre # 修改 next 引用指向
            pre = cur      # pre 暂存 cur
            cur = tmp      # cur 访问下一节点
        return pre

3.4类似题目推荐

大家在做完上面这道题后,如果感觉还可以趁热打铁,可以多做几道题,如下:

🌟移除链表元素

🌟合并有序链表

🌟设计链表(medium)

四、文章结语

如果你已经看到这里了并且感觉这篇文章对你学习链表有所帮助,

那么请不要吝啬你的发财的小手给博主狠狠地扣个

👍 点赞💫收藏 ⭐️ 关注

拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!


 

  • 73
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值