链表中环的口节点

就是剑指offer辣道题没错

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

像求链表的倒数第k个节点一样,我们采用两个一前一后的指针来找位置,同样,我们采用两个指针,如果环中有4个节点,那么就让前面的节点先走4步,后走的节点一会儿肯定会和先走的节点相遇,因为是通过一个环,肯定会在入口处(也就是出口处)遇到,但是问题是:我们不知道这个节点的位置,也不知道环中节点的数目,所以我们:

1、首先判断出节点的入口地址

2、通过两个指针来找出节点的个数

public class Main {
    
    //找到两个元素相遇的位置,如果能相遇肯定在环内
    Node MeetingNode(Node head){
        if(head==null){
            return null;
        }
        Node pSlow=head.next;
        if(pSlow==null){
            return null;
        }
        Node pFast=pSlow.next;
        while(pFast!=null&&pSlow!=null){
            //好巧,快的元素追上了慢的元素
            if(pFast==pSlow){
                return pFast;
            }
            pFast=pFast.next;
            pSlow=pSlow.next;
            
            //我就说么,快的元素一直追,不加快脚步怎么能追上慢的元素
            if(pFast!=null){
                pFast=pFast.next;
            }
        }
        return null;
    }
    
    Node EntryNodeOfLoop(Node head){
        Node meetingNode=MeetingNode(head);
        if(meetingNode==null){
            return null;
        }
        
        //得到环中的节点的个数
        int nodeNum=1;//部位的环至少有一个节点把
        Node pNode =meetingNode;
        while(pNode.next!=meetingNode){
            pNode=pNode.next;
            ++nodeNum;
        }
        
        /**
         * 和那个找倒数K的节点道理一毛一样
         * 让两个元素相隔K个元素,环中的元素肯定一直在环里循环,直达与那个跑的指针相遇,相遇一定在环入口处,你可以画画
         */
        
        pNode=head;
        for(int i=0;i<nodeNum;i++){
            pNode=pNode.next;
        }
        
        Node tNode=head;//让这个元素从头开始遍历,去环里找那个元素
        while(pNode!=tNode){
            pNode=pNode.next;
            tNode=tNode.next;//注意,这里不用加快tnode元素的脚步,因为他两个肯定能遇上,因为pnode在循环,你可以自己画画
        }
        return pNode;
    }
    
    
    
}
class Node{
    int data;
    Node next;
    Node(int data){
        this.data=data;
        this.next=null;
    }
}

不懂可以看注释

posted @ 2021-11-04 23:47  _SpringCloud  阅读(5)  评论(0编辑  收藏  举报  来源