环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回
null。
数据结构:
class ListNode {
val: number
next: ListNode | null
constructor(val?: number, next?: ListNode | null) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
}
}
思路:
判断有环:
同环形链表
判断起始点:
假设快慢指针在图中圆点处相遇,则此时:
因为快指针的速度为慢指针的2倍,所以快指针走过的距离为慢指针的两倍。
慢指针走过的距离为a+b,两倍为2(a+b)。此时快指针已经走过了a,并且在环中走过了n圈,并最终在图中点上相遇。所以快指针走过a+n(b+c)+b。
写成等式为:
2(a+b) = a + n(b+c) + b。
最终获得:a=(n-1)b + nc
通过最终的等式我们可以发现,从head点向后走到入环点的距离为a,从图中相遇圆点的位置走到入环的点距离恰好为(n-1)b + nc,所以此时,我们从head和圆点同时出发,相遇点即为入环点。
代码
function hasCycle(head: ListNode | null): boolean {
let fast = head,slow = head;
while(fast && fast.next){
fast = fast.next.next;
slow = slow.next;
if(fast === slow){
let ptr = head;
while(ptr!=slow){
ptr = ptr.next;
slow = slow.next;
}
return ptr;
}
}
return null;
}