[路飞]_leetcode142.环形链表II

305 阅读1分钟

环形链表 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)
      }
  }

思路:

判断有环:

环形链表

判断起始点:

142_fig1.png 假设快慢指针在图中圆点处相遇,则此时: 因为快指针的速度为慢指针的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;
}