![5f352a2b436048fe20af463aa50a14a6.png](https://img-blog.csdnimg.cn/img_convert/5f352a2b436048fe20af463aa50a14a6.png)
在上篇文章中我们主要介绍了数组和字符串,详情点击查看
力扣(LeetCode):动画学数据结构:轻松掌握数组和字符串zhuanlan.zhihu.com![b106b1dbd0c5f85d16835fb3a93e7af9.png](https://img-blog.csdnimg.cn/img_convert/b106b1dbd0c5f85d16835fb3a93e7af9.png)
本篇文章主要介绍链表。
链表是一种特殊的线性结构,由于不能像数组一样进行随机的访问,所以和链表相关的问题有他自身的特点;在面试中也是非常容易考到的题目,一般代码比较短,而且能够考查面试者的思维全面性和写无 bug 代码的能力。在写链表的题目时,建议画出示意图。
链表链表分单链表和双链表。
单链表
链表中的每个元素实际上是一个单独的对象,而所有对象都通过每个元素中的引用字段链接在一起。
![b744d28cb0b87c17c9a79f8d95b04f91.png](https://img-blog.csdnimg.cn/img_convert/b744d28cb0b87c17c9a79f8d95b04f91.png)
双链表
与单链表不同的是,双链表的每个结点中都含有 两个引用字段。
![9c75138fff408d6f4a2922d15cce840b.png](https://img-blog.csdnimg.cn/img_convert/9c75138fff408d6f4a2922d15cce840b.png)
链表的出现在某种程度上是为了避免数组的一大缺陷,即分配数组的时候需要开辟一段连续的内存空间,但鱼和熊掌不可兼得,链表也牺牲了数组的一些优点,链表不能通过下标进行快速查询。所以在考虑是否需要运用链表的时候,务必要想清楚你的算法是否需要经常进行查询和遍历。
链表的优点
- 能灵活地分配内存空间
- 能在 O(1) 时间内删除或者添加元素,前提是该元素的前一个元素已知,当然也取决于是单链表还是双链表,在双链表中,如果已知该元素的后一个元素,同样可以在 O(1) 时间内删除或者添加该元素。
链表的缺点
查询元素需要 O(n) 时间。不能像数组那样通过下标迅速地读取元素,每次都得从链表的头开始一个一个地读取。
动画演示
![b2a942c67881eeca51aba8c826e0dd7c.gif](https://img-blog.csdnimg.cn/img_convert/b2a942c67881eeca51aba8c826e0dd7c.gif)
解题技巧
链表的解题方法中,最经典的无外乎以下几种:
- 利用快慢指针(有时候需要用到三个指针)
例如,链表的翻转,寻找倒数第 k 个元素,或者寻找链表中间位置的元素,判断链表是否有环等等。
- 构建一个虚假的链表头
动画演示
![64d23f19cd8b6ed34ebb288447402089.gif](https://img-blog.csdnimg.cn/img_convert/64d23f19cd8b6ed34ebb288447402089.gif)
这个方法一般用在要返回新的链表的题目中,例如,给定两个排好序的链表,要求将它们整合在一起并排好序,又比如,将一个链表中的奇数和偶数按照原定的顺序分开后重新组合成一个新的链表,链表的头一半是奇数,后一半是偶数。
在这类问题里,如果不用一个虚假的链表头,那么在创建新链表的第一个元素时,我们都得要判断一下链表的头指针是否为空,也就是要多写一条if else语句,比较简洁的写法是创建一个空的链表头,直接往其后面添加元素即可,最后返回这个空的链表头的下一个节点即可。
如何训练该技巧
- 在纸上或者白板上画出节点之间的相互关系
- 画出修改的方法,这样可以有效地帮助你分析问题,凭空想象是比较困难的,而且,在面试的时候,如果你能把方法画在白板上,还能帮助面试官清楚地看到你的思路。
例题分析
力扣 25.K 个一组翻转链表
题目描述
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
- 你的算法只能使用常数的额外空间。
- 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解决方案
这道题是力扣第24题「两个一组翻转链表」的扩展,即当k = 2时,第25题就变成了第24题。这道题考察了两个知识点:
- 你对链表翻转算法的熟悉程度
- 你对递归算法的理解程度
首先我们要确保给定的链表长度是大于 k 的,这样我们才能够继续,否则直接返回原链表就可以了。
在翻转链表的时候,我们可以借助三个指针:prev、curr、next,分别代表了前一个节点、当前节点和下一个节点。
每次将 curr 指向的下一个节点保存到 next 指针,然后 curr 指向 prev,接着 curr 和 prev 一起前进一步。接着不断地重复之前的步骤,直到把这组当中的 k 个元素翻转完毕。
当完成了局部的翻转后,prev 就是最终的新的链表头,curr 指向了下一个要被处理的局部,而原来的头指针 head 成为了链表的尾巴。
动画演示
![a48e368383987ec8e7bc37173b7eab8f.gif](https://img-blog.csdnimg.cn/img_convert/a48e368383987ec8e7bc37173b7eab8f.gif)
声明:本文归力扣版权所有,未经允许严禁抄袭和翻版。