剑指Offer(链表)-链表中包含环,找环的入口节点
(链表中包含环,找环的入口节点)题目描述:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解决思路:通过判断链表中是否包含有环---判断环中的节点数量---找到环的入口节点
(1)一般判断链表中是否包含有环的解决办法
通过一快一慢的双指针,如果链表中包含的有环的话,两指针是会相遇的,就比如说:两指针一直在移动的话,如果都进入到了环中,那么快的指针肯定能追上并且在某一点与满指针在环中的某个位置相遇。
(2)得到环中的节点数量
这里需要说明的是,两个指针在进入了环之后可以在环中一直移动。
(3)找到环中的入口节点
这里通过第二步找到了环中的节点数量之后,就可以利用环的节点数量来找环的入口节点了。可以让两指针中的一个指针先领先于另外一个指针环状节点数量步,然后让此指针继续跑,在此指针走完了环状节点数量个节点的同时让另外一个指针开始走,此时两指针走的快慢都一致的话,由于先走的指针一直领先于另外一个指针一个环,所以当后走的指针到达环状的入口时,两者刚好相遇,相遇的节点也就即为环状的入口。
/* 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){ return null; } //1、判断链表中是否包含的有环 ListNode low = pHead; ListNode fast = pHead; boolean flag = false; while(fast != null && fast.next != null){ low = low.next; fast = fast.next.next; /** *若存在有环的话,这两个指针是迟早会相遇的 */ if(low == fast){ flag = true; break; } } if(!flag){ return null; } //2、判断环中的节点数量 /** *由于break的时候是两者相遇的时候才break的,所以可以通过移动其中一个指针来计算整体节点数量 */ int n = 1; fast = fast.next;//先移动一位,n加1 while(low != fast){ fast = fast.next; n++; } //3、判断环的入口节点 low = pHead; fast = pHead; while(n!=0){ fast = fast.next; n--; } while(low != fast){ low = low.next; fast = fast.next; } return low;//当相遇时随便返回low或者fast都是环的入口节点位置 } }