链表-链表中环的入口结点

220 阅读1分钟

image.png

方法1: hash,记录第一次出现过的节点

 function EntryNodeOfLoop(pHead){
     let flag = 0;
     let node = pHead;
     while(node) {
         if(node.flag) return node;
         node.flag = 1;
         node = node.next;
     }
 }

方法2: 快慢指针,记录第一次出现过的节点

通过定义slow和fast指针,slow每走一步,fast走两步,若是有环,则一定会在环的某个结点处相遇(slow == fast),这个时候,快慢指针距离头节点的距离是一样的。

  • 头节点到入口节点有a点,环中的节点有b个
  • 设fast指针走过的节点数是f,
  • slow指针走过的节点数是s,
  • 那么有以下两个结论:
    • f = 2 * s (即快指针走过的节点数一定是慢指针的两倍)
    • f = s + nb (当两者相遇时,快指针一定已经绕环走了n圈)
  • 上面表达式得出 s = nb
  1. 相遇时慢指针已经走了nb步,要走到入口节点,需要走a + kb步,而这时s = nb 慢指针只要再走a即可到达入口,a刚好是头节点到入口节点的距离。
  2. 此时若把快指针移动到头节点,然后和🈵慢指针一样的速度,当它们相遇时所处的位置就是入口节点
function EntryNodeOfLoop(pHead)
{
    let fast = pHead;
    let slow = pHead;
    while(fast && fast.next) {
        fast = fast.next.next;
        slow = slow.next;
        if(slow === fast) break;
    }
    if(fast == null || fast.next == null) return null;
    fast = pHead;
    while(fast !== slow) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}