剑指offer——链表中环的入口节点
继续链表。原题目链接:链表中环的入口节点。
题目描述:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
题目分析:
首先需要判断链表中是否有环;其次是寻找入口节点。
相关内容需要推导,详细过程可参见博客:单链表面试题系列之带环链表的入口点。这个博客也很清晰明了:Java--链表中环的入口节点(两种方法实现)。
这里直接采用结论。
如何判断链表是否有环:设置快慢指针,slow和fast。slow每次走一步;fast每次走两步。若链表带环,则两个指针必然会相遇,且相遇点必然在环内。
判断是否有环的方法实现如下:
1 public boolean judge_ring(ListNode pHead){ 2 ListNode slow = null; 3 ListNode fast = null; 4 slow = fast = pHead; //刚开始都指向第一个节点 5 6 while(fast!=null && fast.next!=null){ 7 slow = slow.next; //每次走一步 8 fast = fast.next.next; //每次走两步 9 if(slow == fast){ 10 return true; //若有环,则必定会相遇 11 } 12 } 13 return false; //若直接走到头,则没有环 14 }
如何寻找入口节点:设置两个指针,分别从表头和相遇点出发,每次走一步,则必然会在环入口相遇。
利用此结论,便可得到本题的解决方案,实现代码如下所示:
1 public ListNode EntryNodeOfLoop(ListNode pHead){ 2 ListNode slow = null; 3 ListNode fast = null; 4 slow = fast = pHead; //刚开始都指向第一个节点 5 6 while(fast!=null && fast.next!=null){ 7 slow = slow.next; //每次走一步 8 fast = fast.next.next; //每次走两步 9 if(slow == fast){ 10 break; //若有环,则必定会相遇 11 } 12 } 13 if(fast==null || fast.next==null){ 14 return null; //若没有相遇,则无环 15 } 16 ListNode meet = fast; //记录相遇节点 17 slow = pHead; //重新回到第一个节点 18 19 while(slow!=meet){ //一定会相遇在入口节点 20 meet = meet.next; 21 slow = slow.next; 22 } 23 return meet; 24 }