天长网站设计,wordpress 企业网站主题,新房网站建设,安卓开发文档大家好#xff01;我是曾续缘#x1f61b; 今天是《LeetCode 热题 100》系列 发车第 26 天 链表第 5 题 ❤️点赞 #x1f44d; 收藏 ⭐再看#xff0c;养成习惯 环形链表 II 给定一个链表的头节点 head #xff0c;返回链表开始入环的第一个节点。 如果链表无环#xf… 大家好我是曾续缘 今天是《LeetCode 热题 100》系列 发车第 26 天 链表第 5 题 ❤️点赞 收藏 ⭐再看养成习惯 环形链表 II 给定一个链表的头节点 head 返回链表开始入环的第一个节点。 如果链表无环则返回 null。 如果链表中有某个节点可以通过连续跟踪 next 指针再次到达则链表中存在环。 为了表示给定链表中的环评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置索引从 0 开始。如果 pos 是 -1则在该链表中没有环。注意pos 不作为参数进行传递仅仅是为了标识链表的实际情况。 不允许修改 链表。 示例 1 输入head [3,2,0,-4], pos 1
输出返回索引为 1 的链表节点
解释链表中有一个环其尾部连接到第二个节点。示例 2 输入head [1,2], pos 0
输出返回索引为 0 的链表节点
解释链表中有一个环其尾部连接到第一个节点。示例 3 输入head [1], pos -1
输出返回 null
解释链表中没有环。提示 链表中节点的数目范围在范围 [0, 104] 内-105 Node.val 105pos 的值为 -1 或者链表中的一个有效索引 进阶你是否可以使用 O(1) 空间解决此题 难度 解题方法
寻找链表中环的入口节点
这道题需要找到链表中环的入口节点我们同样可以使用快慢指针的算法来解决。
假设从链表头部到环的入口有 a a a 个节点环中有 b b b 个节点。一个指针要走到入口处其走过的步数 k k k 满足 k a n × b k a n \times b kan×b 的数学关系。这意味着要么直接走 a a a 步到达入口要么先走到入口然后绕环 n n n 圈回到入口。
通过快慢指针可以检测链表是否存在环。当快慢指针相遇时假设快指针走过的步数为 f f f慢指针走过的步数为 s s s则有以下关系
快指针速度是慢指针的两倍即 f 2 × s f 2 \times s f2×s快慢指针在环内相遇快指针比慢指针多走了 n n n 圈因此 f s n × b f s n \times b fsn×b
通过上述方程组我们得到重要的信息 s n × b s n \times b sn×b这意味着什么呢
当快慢指针相遇时慢指针走过的步数是环节点数的整数倍
为了使慢指针到达环的入口即满足 k a n × b k a n \times b kan×b只需让慢指针再走 a a a 步即可或者继续多走几圈再返回。
然而 a a a 是未知数我们并不知道具体需要走多少步该怎么办呢 a a a 表示链表头部到链表入口的节点数我们可以将快指针置于链表头部与慢指针速度相同。当它们再次相遇时它们之间的距离差就是链表头部到链表入口的节点数因此我们也就获得了 a a a慢指针正好满足入口公式的条件。
过程如下
首先设定两个指针 slow 和 fast初始化它们都指向头节点。使用一个 do…while 循环循环内部判断快指针和快指针的下一个节点是否为空如果有一个为空则说明链表无环直接返回 null。在循环内部快指针每次向前移动两步慢指针每次向前移动一步直到它们相遇。当快指针和慢指针相遇时将快指针重新指向头节点并将快指针和慢指针都以每次一步的速度向前移动。当快指针和慢指针再次相遇时相遇的节点即为环的入口节点。
Code
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
public class Solution {public ListNode detectCycle(ListNode head) {if (head null) {return null;}ListNode slow head, fast head;do {if (fast null || fast.next null) {return null;}fast fast.next.next;slow slow.next;} while (fast ! slow);fast head;while (fast ! slow) {fast fast.next;slow slow.next;}return fast;}
}