剑指offer-链表-寻找一个链表中的环入口

题目

一个链表中包含环,请找出该链表的环的入口结点

个人思路分析

一定要保证思维有序,分析问题后即使最后没有得到最完美的答案,至少方向正确不能跑偏。

  • 链表结构
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

根据题目中对链表的定义 ==> 环必不可能出现在链表中部

  • 环特点/性质
    首尾相连,末尾节点next引用指向链表头 ==> 基本确定需要两个指针,检测指针相遇情况

  • 核心问题
    1. 若链表带环,遍历终止条件难以确定
    2. 环长度不明,标记入口难度大

offer巧妙解法

  • 在基本思考的基础上,采用快慢指针标记环入口
  • 结合追击问题特点,快第一次追上慢一定比慢多走了一圈环长
  • 所以将快慢相遇作为遍历终止条件,并得到环长
  • 灵活转换成查找链表中倒数第k个节点问题
  • 注意细节:计数问题 ==> 倒数k,快指针应该先走几步

MyCode

public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if (pHead == null || pHead.next == null)
            return null;

        if (pHead.next.next == null)
            return pHead;

        ListNode pfast = pHead, pslow = pHead;
        int fastCounter = 0, slowCounter = 0;
        while (true) {
            pfast = pfast.next.next;
            pslow = pslow.next;
            fastCounter += 2;
            slowCounter++;

            if (pfast == pslow)
                break;
        }

        // one loop faster
        int loopLength = fastCounter - slowCounter;
        pfast = pHead;
        pslow = pHead;
        for (int i = 1; i <= loopLength; i++) {
            pfast = pfast.next;
        }
        while (pfast != pslow) {
            pfast = pfast.next;
            pslow = pslow.next;
        }
        if (pfast == pslow)
            return pslow;

        return null;
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_22153679/article/details/80162023