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

链表中环的入口结点-链表专题_第1张图片
链表中环的入口结点-链表专题_第2张图片
简述:
题目的要求主要就是一个带环的链表(无需证明是否带环),我们要找到具体是链表那个结点作为入环结点,例如上方345为环结点,3为环入口,故我们只需想办法弄出3这个结点。
首先
这个题目我主要用的解法是(不需要知道环中结点数目的解法),算法题目一定要先在脑海里构思,具体的步骤是如何的。先来简单讲一下需要知道环中节点数目的解法是如何解决这个题目的,这个比较简单,很多人应该最开始想到的解法就是这个。

依旧是常规的双指针的解法,第一步,设置快慢指针,P1为快指针,P2为慢指针,让他们都指向头节点。第二步我们需要求出这个链表中的环中的结点个数(N),然后快指针先走N步。第三步,快指针和慢指针以同样的速度向前走,当快指针和慢指针相遇的时候,相遇的那个结点就是环的入口结点。(以下图为例)
链表中环的入口结点-链表专题_第3张图片

接下来主要介绍的是不需要知道环中结点数目的解法。上面讲的解法虽然很容易想到,但是代码量其实也是不少的,需要先要求出环中的节点数目然后在双指针求相遇结点。如果仔细分析,就会发现其实并没有必要求得环中节点得数目。设快指针每次走两步,慢指针每次走一步,如果链表中有环,快慢两个指针一定会在环中的某个节点相遇,我们可以先假设一种特殊情况来分析整个过程(快指针只在环中循环一圈就遇到了慢指针),设起始点到环的入口距离为X,相遇点到环的入口为Y,环的一圈距离为C,那么慢指针走过的距离就是X+C-Y,快指针走过的距离就是X+C+C-Y,又因为快指针的速度是慢指针的速度的两倍,所以可以得到2(X+C-Y)=X+C+C-Y。化简之后,可以得到一个结论X=Y,也就是起始点到环的入口的距离一定等于相遇点到环的入口的距离,得到这个结论之后所有问题都迎刃而解了,在快慢指针相遇之后,我们只需要再设一个指针指向起始点,然后让相遇点的慢指针和起始点指针以同样的速度向前走,当起始点指针与慢指针相遇时,相遇点就是环的入口。
链表中环的入口结点-链表专题_第4张图片
贴代码

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
         if(pHead==null||pHead.next==null)//判断链表是否存在和特殊情况
        {
            return null;
        }
        ListNode fast=pHead;//快指针
        ListNode slow=pHead;//慢指针
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;//快指针一次走两步
            slow=slow.next;//慢指针一次走一步
            if(fast==slow){
                ListNode slow2=pHead;起始点指针
               while(slow2!=slow){  //判断起始指针和慢指针相遇,相遇点为环的入口点
                   slow2=slow2.next;
                   slow=slow.next;
               }
               return slow2;
            }
        }
        return null;
    }
}

链表中环的入口结点-链表专题_第5张图片

你可能感兴趣的:(算法,链表,数据结构)