链表中环的入口结点

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

分析
在这里插入图片描述

  • 第一步:确定一个链表中是否有环
    我们可以用两个指针来解决,定义两个指针,同时从链表的头结点触发,一个指针一次走一步,另一个指针一次走两步。如果走的块的指针追上了走的慢的指针,那么链表就包含环。如果走得快的只恨走到链表的末尾都没有追上走的慢的,那么链表就没有环。
  • 第二步:如何找到环的入口
    还是利用两个指针来解决,先定义两个指针p1p_1p2p_2指向链表的头结点,如果链表中的环有n个节点,那么指针p1p_1现在链表上向前移动n步,然后两个指针按相同速度向前移动,当第二个指针指向环的节点入口时,第一个指针已经围绕着环走了一圈,又回到入口节点。
  • 第三步:如何知道环中节点的数目
    在第一步中判断一个链表里是否有环时用到一快一慢两个指针,如果两个指针相遇,那么有环,两个指针相遇的节点一定在环中,那么就可以从这个节点触发,一边继续向前移动一边计数,当再次回到这个节点时就可以得到环中节点的点数。

节点类:

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 meet = MeetNode(pHead);
        
        if(meet == null ) {
        	return null;
        }
        
        int nodeInLoop = 1;
        ListNode pNode = meet, pNode2 = pHead;
        while(pNode.next != meet) {
        	pNode = pNode.next;
        	++nodeInLoop;
        }
        
        pNode = pHead;
        
        for (int i = 0; i < nodeInLoop; i++) {
			pNode = pNode.next;
		}
        
        while(pNode != pNode2) {
        	pNode = pNode.next;
        	pNode2 = pNode2.next;
        }
        return pNode;
        
    }
    
    public ListNode MeetNode(ListNode head) {
    	if(head == null) {
    		return null;
    	}
    	
    	ListNode slow = head.next;
    	if(slow == null) {
    		return null;
    	}
    	
    	ListNode fast = slow.next;
    	
    	while(fast != null && slow != null) {
    		if(fast == slow) {
    			return slow;
    		}
    		slow = slow.next;
    		fast = fast.next;
    		
    		if(fast != null) {
    			fast = fast.next;
    		}
    	}
    	
    	return null;
    }
    
}
posted @ 2019-04-09 22:01  如是说  阅读(308)  评论(0编辑  收藏  举报