题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
下面给出两种方法,分别使用哈希表和双指针
双指针示意图如下图所示
/*
使用 hashMap 返回第一次出现的重复结点
*/
public ListNode EntryNodeOfLoop1(ListNode pHead){
HashMap<ListNode,Integer> hashMap = new HashMap<>();
ListNode pnode = pHead;
while (pnode != null){
hashMap.put(pnode, hashMap.getOrDefault(pnode, 0)+1);
if (hashMap.get(pnode) == 2)
return pnode;
pnode = pnode.next;
}
return null;
}
/*
示意图在上面
指针 slow fast: slow 一次走 一步,fast 一次走 2 步;
设从链表开始到环入口距离为 s,当快慢指针相遇时,slow 在环里走了 d 步,环长度为 d+ m
设此时快指针走了 n 圈 , n(m+d) +d + s = 2(s+d)
化简一下上述式子则有 n(m+d) = s+ d
s = n*m + (n - 1)*(m+d)
*/
public static ListNode EntryNodeOfLoop2(ListNode pHead){
if (pHead == null)
return null;
ListNode slow = pHead;
ListNode fast = pHead;
//寻找环
while (fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if (fast == slow)
break;
}
if (fast == null || fast.next == null)
return null;
//在找到环的相遇点
slow = pHead;
while (fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}