51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

算法学习笔记 —— 链表

学而时习,本文记录链表操作相关算法练习笔记。

反转链表 {#反转链表}

题目描述 {#题目描述}

输入一个链表,反转链表后,输出新链表的表头。

解题代码 {#解题代码}

复杂度 {#复杂度}

| 时间 | 空间 | |------|------| | O(n) | O(1) |

解题备注 {#解题备注}

  • 维护当前节点,顺带考虑前后节点,会比较稳健
  • 设置虚拟前置节点,现场生成后置节点,更加鲁棒,甚至同时囊括了输入为None的情况
  • 需要注意返回前置节点作为新链表头

两个链表是否相交 {#两个链表是否相交}

这个问题有意思,也是力扣第 160 题「相交链表open in new window」函数签名如下:

给你输入两个链表的头结点 headAheadB,这两个链表可能存在相交。

如果相交,你的算法应该返回相交的那个节点;如果没相交,则返回 null。

比如题目给我们举的例子,如果输入的两个链表如下图:

那么我们的算法应该返回 c1 这个节点。

这个题直接的想法可能是用 HashSet 记录一个链表的所有节点,然后和另一条链表对比,但这就需要额外的空间。

如果不用额外的空间,只使用两个指针,你如何做呢?

难点在于,由于两条链表的长度可能不同,两条链表之间的节点无法对应:

如果用两个指针 p1p2 分别在两条链表上前进,并不能同时 走到公共节点,也就无法得到相交节点 c1

解决这个问题的关键是,通过某些方式,让 p1p2 能够同时到达相交节点 c1

所以,我们可以让 p1 遍历完链表 A 之后开始遍历链表 B,让 p2 遍历完链表 B 之后开始遍历链表 A,这样相当于「逻辑上」两条链表接在了一起。

如果这样进行拼接,就可以让 p1p2 同时进入公共部分,也就是同时到达相交节点 c1

那你可能会问,如果说两个链表没有相交点,是否能够正确的返回 null 呢?

这个逻辑可以覆盖这种情况的,相当于 c1 节点是 null 空指针嘛,可以正确返回 null。

判断链表是否包含环 {#判断链表是否包含环}

判断链表是否包含环属于经典问题了,解决方案也是用快慢指针:

每当慢指针 slow 前进一步,快指针 fast 就前进两步。

如果 fast 最终遇到空指针,说明链表中没有环;如果 fast 最终和 slow 相遇,那肯定是 fast 超过了 slow 一圈,说明链表中含有环。

当然,这个问题还有进阶版,也是力扣第 142 题 环形链表:如果链表中含有环,如何计算这个环的起点?

可以看到,当快慢指针相遇时,让其中任一个指针指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置。

为什么要这样呢?这里简单说一下其中的原理。

我们假设快慢指针相遇时,慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步:

fast 一定比 slow 多走了 k 步,这多走的 k 步其实就是 fast 指针在环里转圈圈,所以 k 的值就是环长度的「整数倍」。

假设相遇点距环的起点的距离为 m,那么结合上图的 slow 指针,环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。

巧的是,如果从相遇点继续前进 k - m 步,也恰好到达环起点。因为结合上图的 fast 指针,从相遇点开始走k步可以转回到相遇点,那走 k - m 步肯定就走到环起点了:

所以,只要我们把快慢指针中的任一个重新指向 head,然后两个指针同速前进,k - m 步后一定会相遇,相遇之处就是环的起点了。

删除链表的倒数第 N 个结点 {#删除链表的倒数第-N-个结点}

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

合并两个有序链表 {#合并两个有序链表}

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

分隔链表 {#分隔链表}

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

链表的中间结点 {#链表的中间结点}

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

合并 K 个升序链表 {#合并-K-个升序链表}

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

206. 反转链表 {#206-反转链表}

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

92. 反转链表 II {#92-反转链表-II}

给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表

参考资料 {#参考资料}



文章链接:
https://www.zywvvd.com/notes/study/algorithm/list/about-list/

赞(0)
未经允许不得转载:工具盒子 » 算法学习笔记 —— 链表