当前位置: 首页 > news >正文

2.链表算法

2.1 常见算法题

  1. 1. 合并两个有序链表

  2. 2. 分隔链表

  3. 3. 合并 K 个升序链表

  4. 4. 删除链表的倒数第 N 个结点

  5. 5. 链表的中间结点

  6. 6. 环形链表 I 、环形链表 II

  7. 7. 相交链表

这些解法都用到了双指针技巧,对于单链表相关的题目,双指针的运用是非常广泛的。

2.2 经典习题

  1. 8. 删除排序链表中的重复元素 II

  2. 9. 有序矩阵中第 K 小的元素

  3. 10. 查找和最小的 K 对数字

  4. 11. 两数相加、两数相加 II

2.3 花式翻转

反转单链表的迭代解法不是一个困难的事情,但是递归实现就有点难度了。如果再加一点难度,仅仅反转单链表中的一部分,是否能够同时用迭代和递归实现呢?再进一步,如果 k 个一组反转链表,阁下又应如何应对?

  1. 12. 反转链表

对于「分解问题」思路的递归算法,最重要的就是明确递归函数的定义。具体来说,我们的 reverseList 函数定义是这样的:输入一个节点 head,将「以 head 为起点」的链表反转,并返回反转之后的头结点。

不要跳进递归(你的脑袋能压几个栈呀?),而是要根据刚才的函数定义,来弄清楚递归代码会产生什么结果:

Image

这个 reverseList(head.next) 执行完成后,整个链表就成了这样:

Image

有两个地方需要注意:

  • 递归函数要有 base case,意思是如果链表为空或者只有一个节点的时候,反转结果就是它自己,直接返回即可。
  • 当链表递归反转之后,新的头结点是 last,而之前的 head 变成了最后一个节点,别忘了链表的末尾要指向 null。

❤️

递归操作链表的效率不如迭代

值得一提的是,递归操作链表并不高效。

递归解法和迭代解法相比,时间复杂度都是 O(N),但是迭代解法的空间复杂度是 O(1),而递归解法需要堆栈,空间复杂度是 O(N)。

所以递归操作链表可以用来练习递归思维,但是考虑效率的话还是使用迭代算法更好。

  1. 13. 反转链表 II

  2. 14. K 个一组翻转链表

总结:

递归的思想相对迭代思想,稍微有点难以理解,处理的技巧是:不要跳进递归,而是利用明确的定义来实现算法逻辑。

处理看起来比较困难的问题,可以尝试化整为零,把一些简单的解法进行修改,解决困难的问题。

2.4 回文链表

  • 寻找回文串的核心思想是从中心向两端扩展。
  • 而判断一个字符串是不是回文串就简单很多,不需要考虑奇偶情况,只需要双指针技巧,从两端向中间逼近即可。

  1. 15. 回文链表

最简单的办法就是,把原始链表反转存入一条新的链表,然后比较这两条链表是否相同。

优化后就是 先找到中间节点,翻转半部分链表再遍历对比。

2.2 常用技巧

  • 「虚拟头节点」技巧:也就是dummy节点,当需要创造一条新的链表(并非是 new 一个)的时候,可以使用虚拟头结点简化边界情况的处理。如果不用就需要特判指针为 null 的情况去处理。
  • 「快慢双指针」技巧:利用 fast、slow 指针,可以是 fast 先移动,也可以是同时移动,fast 每次移动多步,用 fast、slow 两个指针的状态或者位置来达到某个目标。

    在题 6 链表判环中,fast 与 slow 相遇则有环,利用了两个指针的状态;

    在题 5 寻找中间节点中,fast 走到终点,则表示 slow 走到中间,利用了两个指针的位置关系。

  • 「链表分解」技巧:链表的分解技巧可以运用到很多单链表题目中,题目并不一定明确地要求你把链表分解成两部分,只要要求你从链表筛选出若干节点,都可以用这个技巧。

    题 8 删除排序链表中的重复元素,就可以理解为 一条链表存放不重复的节点,另一条链表存放重复的节点

  • 「多路归并」技巧:是指将多个有序序列合并成一个有序序列的算法技术。问题本质:有 K 个有序序列;需要将它们合并成一个有序序列;关键:每次选择当前所有序列中最小的元素,有些时候题目没有明确给出 K 个有序序列,但可以转化。使用优先队列(最小堆)来维护各个序列的当前最小元素,每次取出堆顶元素,然后将该元素所在序列的下一个元素加入堆中。

    题 3、9、10 都可以用「多路归并」技巧解答,先将题目数据转化为 k 个有序序列,再结合优先队列维护最小堆,直接获取所需数据。

  • 「虚拟链表」技巧:多用于将数组虚拟化为链表,逻辑上当链表来使用,如将二维问题转化为链表合并问题,在「多路归并」相关题目中使用较多。过程中还需「索引维护」以及「边界控制」等细节设计。
  • 「分解问题」思路:如果问题有子问题结构,即可以转化为树形结构,那么可以用递归来求解子问题。

    题 13、14 的反转链表就可以分解为子问题,不直接操作当前节点,而是反转子链表,然后与当前节点拼接,处理交给递归即可,定义好递归函数,以及 base case。


文章转载自:

http://53snxclH.sjwws.cn
http://PF4FW1IW.sjwws.cn
http://A2ZXVTFX.sjwws.cn
http://BDLvD4GD.sjwws.cn
http://CqxoWxc6.sjwws.cn
http://JAOnPTpF.sjwws.cn
http://ZTFX4SHO.sjwws.cn
http://D1i6Gybt.sjwws.cn
http://H9Fi45m0.sjwws.cn
http://K16E0cQl.sjwws.cn
http://OJYifozI.sjwws.cn
http://KszTg5vo.sjwws.cn
http://74vYv9og.sjwws.cn
http://KfCqSulS.sjwws.cn
http://PSI0qxGK.sjwws.cn
http://pRYDWvcN.sjwws.cn
http://OA3GD8tX.sjwws.cn
http://eSVq2gde.sjwws.cn
http://uhdFtJeq.sjwws.cn
http://QOh0S21s.sjwws.cn
http://0MO4aGCU.sjwws.cn
http://KH7jhLI1.sjwws.cn
http://bTn7O09J.sjwws.cn
http://E37TiAxp.sjwws.cn
http://aGahVXIT.sjwws.cn
http://3AP9Y4da.sjwws.cn
http://ujMnjTMq.sjwws.cn
http://QjvgdcDf.sjwws.cn
http://M5jjSdGk.sjwws.cn
http://cUkBiF9S.sjwws.cn
http://www.dtcms.com/a/372342.html

相关文章:

  • Visual Studio Code的第一次安装
  • 基于 Visual Studio 2017 安装配置 GDAL 库的详细步骤
  • JMeter介绍以及使用详解
  • 一个Java的main方法在JVM中的执行流程
  • whl编译命令使用场景举例
  • 【Leetcode】高频SQL基础题--1164.指定日期的产品价格
  • 力扣1210. 穿过迷宫的最少移动次数 详解
  • Redis 从入门到精通:全平台安装与性能优化配置指南
  • RestClient查询和数据聚合
  • 前后端中的回调机制:含义、作用与实现详解
  • 四、神经网络的学习(下)
  • 万字详解网络编程之socket
  • PNG和JPEG和BMP文件格式转换
  • 语音之战+通用大模型,AI霸权决战打响
  • eslint 和 prettier 的相同点和区别
  • 苹果 FoundationModels 秘典侠客行:隐私为先的端侧 AI 江湖
  • hot100链表类题目
  • 算法:链表
  • Vscode中开发VUE项目的调试方案
  • Lua > OpenResty HelloWorld
  • FreeRTOS项目(2)摇杆按键检测
  • 《一往无前:雷军亲述小米热血 10 年》(上部)读书笔记
  • 线性代数 | 行图像 / 列图像
  • 【PCIe EP 设备入门学习专栏 -- 8.2.1 PCIe EP Capability Register 介绍】
  • 基于Python的在线课程学习平台【2026最新】
  • 矩阵的对称,反对称分解
  • [论文阅读] 人工智能 + 软件工程 | 从Dialogflow到Rasa:MUTABOT如何让聊天机器人缺陷无所遁形?
  • 视频软件 SMPLAYER
  • AutoGPT实战体验:AI自动任务工具如何高效完成深度调研?避坑技巧分享
  • tcp粘包产生的根源