1、题目描述
2、算法分析
方法一:使用Set集合
本题求的是链表中环的入口结点,可以使用Set集合。
将链表中的结点存储到Set集合中,若链表中有环,必然存在重复的结点。
只需要遍历链表的结点,然后存储在Set集合中,找出重复的结点必然是环的入口结点。
方法二:使用快慢指针
定理记住:
若链表是有环的链表。定义两个指针,一个slow,一个fast指针,同时从链表的头部出发,fast指针走2步,slow指针走1步。若该链表有环,那么fast和slow必然会在环内相遇。也可能在环的入口结点,也可能在环中的任意其他结点。
此时只需要将slow,fast中的其中一个指针再指向链表的头部pHead,另一个不变(在环内),接下来slow,fast指针一次走一步,相遇的地方就是环的入口结点。
具体看代码。
3、代码实现
方法一:使用Set集合
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
if(pHead == null){
return null;
}
Set<ListNode> set = new HashSet<>();
while(pHead != null){
if(set.contains(pHead)){
return pHead;
}
set.add(pHead);
pHead = pHead.next;
}
return null;
}
}
方法二:使用快慢指针
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
ListNode slow = pHead;
ListNode fast = pHead;
//判断fast指针就可以了
while(fast != null && fast.next != null){
slow = slow.next;
// fast指针走2步
fast = fast.next.next;
if(fast == slow){
break;
}
}
// 注意 不能将fast.next放在条件前面
if(fast == null || fast.next == null){
return null;
}
slow = pHead;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}