剑指Offer(书):链表中环的入口节点

题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

public ListNode EntryNodeOfLoop(ListNode pHead) {
    //第一步,查找是否有环。
    ListNode meetingNode = findIsHoop(pHead);
    if (meetingNode == null) {
        return null;
    }
    //第二步,查找环中节点的个数
    int number = findNodeNumberForHoop(meetingNode);
    //第三步,查找入口节点
    ListNode tempHead = pHead;
    for (int i = 0; i < number; i++) {
        tempHead = tempHead.next;
    }

    ListNode tempHead1 = pHead;
    while (tempHead != tempHead1) {
        tempHead = tempHead.next;
        tempHead1 = tempHead1.next;
    }
    return tempHead;
}


/**
 * 查找环中节点的数量
 * @param meetingNode 环中的节点
 * @return 节点的数量
 */
private int findNodeNumberForHoop(ListNode meetingNode) {
    ListNode tempNode = meetingNode;
    int number = 1;
    while (meetingNode.next != tempNode) {
        meetingNode = meetingNode.next;
        number++;
    }
    return number;
}

/**
 * 寻找是否有环。使用两个指针来判断,一个指针走一步,一个指针走两步,若有环则走两步的必定能够追上走一步的。
 *
 * @param pHead 头结点
 * @return 若有环,返回环中的某一位置;否则,返回null;
 */
private ListNode findIsHoop(ListNode pHead) {
    if (pHead == null) {
        return null;
    }
    ListNode pSlow = pHead.next;
    if (pSlow == null) {
        return null;
    }
    ListNode pFast = pSlow.next;
    if (pFast == null) {
        return null;
    }
    while (pFast != null && pSlow != null) {
        if (pFast == pSlow) {
            return pFast;
        }
        pSlow = pSlow.next;
        pFast = pFast.next;
        if (pFast != null) {
            pFast = pFast.next;
        }
    }
    return null;
}
原文地址:https://www.cnblogs.com/liter7/p/9444425.html