660 字
3 分钟
LeetCode-142.环形链表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解释:链表中没有环。
自己的解法(哈希)
手撕,暴力法哈哈
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */func detectCycle(head *ListNode) *ListNode { cur := head res := make(map[*ListNode]int)
for cur != nil { if res[cur] == 1 { return cur } res[cur]++ cur = cur.Next }
return nil}快慢指针
第一个想出来快慢指针的人,简直就是天才,太神奇了
思路:快慢指针必然在环内的某一点相遇。我们把整段路程切成三段:
- x:从链表头到环入口的距离。
- y:从环入口到相遇点的距离。
- z:从相遇点继续走,回到环入口的距离
-
首先,我们要先知道慢指针在进入环之后,绝对不可能走完一整圈,它必定会在第一圈内就被快指针追上。fast和slow的相对速度是1,最大距离是L-1,所以相遇时慢指针移动L-1,L-1 < L,慢指针走过的距离也严格小于环的总长度。
-
我们可以得出 慢指针距离:x + y,快指针距离:x + y + n(y + z) 或 2(x + y)
-
2(x + y) = x + y + n(y + z) 得到 x = n(y + z) - y
-
化简一下 x = (n - 1)(y + z) + z,即他们相遇的点就是我们所求的答案
func detectCycle(head *ListNode) *ListNode { slow, fast := head, head
for fast != nil && fast.Next != nil { fast = fast.Next.Next slow = slow.Next
if slow == fast { left := head right := slow
for left != right { left = left.Next right = right.Next }
return left } } return nil} LeetCode-142.环形链表II
https://sheep44044.github.io/posts/算法/链表/leetcode-142环形链表ii/


