题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null
思路一:
使用HashMap或者HashSet,从头开始遍历链表,如果HashMap中不存在该节点,将该节点放入HashMap中,如果已经存在了,说明该节点一定是环的入口节点。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
HashMap<ListNode,Integer> map = new HashMap<>();
ListNode cur = pHead;
while(cur!=null){
if(!map.containsKey(cur)){
map.put(cur,1);
cur = cur.next;
}else{
return cur;
}
}
return null;
}
}
思路二:
快慢指针。假设链表中环的长度为n,让快指针先走n个节点,然后让快指针与慢指针以相同的速度遍历,它们一定会在环的路口相遇。
分析:假设链表共有m个节点,环长度为n,快指针先走n个节点,还剩m-n个节点走完全程
慢指针距离环路口的距离为m-n,最后一定会在环路口相遇。
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
ListNode meetNode = getLoopMeetNode(pHead);
if(meetNode==null){
return null;
}
ListNode mn = meetNode;
// 环的长度
int loopLen = 1;
while(mn.next!=meetNode){
loopLen++;
mn = mn.next;
}
//p1 先走环的长度
ListNode p1 = pHead;
for(int i=0;i<loopLen;i++){
p1 = p1.next;
}
//p1与p2以相同的速度前进
ListNode p2 = pHead;
// p1与p2相遇一定在环的入口节点
while(p1!=p2){
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
// 快慢指针,相遇一定在环中 ,为了求出环的长度
public ListNode getLoopMeetNode(ListNode head){
if(head==null){
return null;
}
ListNode slow = head.next;
if(slow==null){
return null;
}
ListNode quick = slow.next;
while(slow!=null&&quick!=null){
// 两个指针相遇一定在环中
if(slow==quick){
return slow;
}
slow = slow.next;
quick = quick.next;
if(quick!=slow){
quick = quick.next;
}
}
return null;
}
}