《剑指offer第二版》面试题23:链表中环的入口节点(java)

题目描述

如果一个链表中包含环,如何找出环的入口?

解题思路:

  1. 先判断是否有环,如果没有话则没有入口:定义快慢指针slow, fast都指向头节点;遍历链表,slow一次走一步,fast一次走两步,如果slow和fast能相遇,则说明有环,记录相遇的节点为loopNode。
  2. 计算环的长度:从第1步里的loopNode开始循环,再次遍历到loopNode的时候,则将环遍历了一圈,可以算出环的长度n。
  3. 再次定义快慢指针slow, fast都指向头节点,fast先走n步骤,然后slow和fast同时每次走一步向后遍历,等到slow和fast相遇,则是环的入口。

代码

ListNode entryNodeOfLoop(ListNode head) {
    if (head == null) {
        return null;
    }
    // 先找出链表是否有环
    ListNode slow = head;
    ListNode fast = head;
    ListNode loopNode = null;
    while (true) {
        if (fast.next == null || fast.next.next == null) {
            break;
        }
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) {
            loopNode = fast;
            break;
        }
    }

    if (loopNode == null) {
        // 说明没有环
        return null;
    }

    // 找出环的长度
    ListNode loopNodeTmp = loopNode.next;
    int loopLength = 1;
    while(loopNodeTmp != loopNode) {
        loopNodeTmp = loopNodeTmp.next;
        loopLength ++;
    }

    // 找出环的入口
    slow = head;
    fast = head;
    for (int i = 0; i < loopLength; i++) {
        fast = fast.next;
    }
    while (fast!= slow) {
        fast = fast.next;
        slow = slow.next;
    }
    return fast;
}

你可能感兴趣的:(《剑指offer第二版》面试题23:链表中环的入口节点(java))