import java.util.HashSet;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
//方法一:利用集合元素的唯一性,运行时间大概是80ms
//特殊值处理,链表为空
// if(pHead == null){
// return null;
// }
// ListNode head0 = pHead;
// //创建一个哈希集合,存储对象为ListNode
// HashSet<ListNode> hashSet = new HashSet<>();
// //遍历链表,如果在哈希集合中存在该节点,即链表存在环;否则,将该节点添加到哈希集合中
// while (head0 != null){
// if(hashSet.contains(head0)){//哈希集合中存在该节点,该节点即为链表中环的入口节点,并返回该节点
// return head0;
// }else{//哈希集合中不存在该节点,将该节点添加到哈希集合中
// hashSet.add(head0);
// }
// head0 = head0.next; //节点移动
// }
// return null;
//方法二:利用快慢指针,运行时间大概是60ms
//特殊值处理,链表为空或者链表的长度为1
if(pHead == null || pHead.next == null){
return null;
}
ListNode fast = pHead.next.next; //初始化快指针
ListNode flow = pHead.next; //初始化慢指针
boolean flag = false; //标记值,如果为true代表是相遇后,反之,代表相遇前
while (flow != null && fast != null){ //遍历链表,当快慢指针都不为空时,
if(flow == fast){//如果快慢指针指向同一个节点,则代表有环
if(flag){//相遇后再次相遇,则此节点为链表环的入口节点
return flow;
}else{
fast = pHead;//相遇后,更新快指针指向头节点,满指针原地不动,此后快慢指针每次走一步
}
flag = true;
}else{//如果快慢指针不是指向同一个节点,更新快慢指针
if(flag){//相遇后,更新快指针指向头节点,满指针原地不动,此后快慢指针每次走一步
flow = flow.next; //慢指针每次走一步
fast = fast.next; //快指针每次走一步
}else{
flow = flow.next; //慢指针每次走一步
fast = fast.next; //快指针每次走两步
if(fast != null){//快指针每次走两步,可能存在刚走完一步就是空指针,所以要验证快指针为非空
fast = fast.next;
}
}
}
}
return null;
}
}
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead) {
//方法一:利用集合元素的唯一性,运行时间大概是80ms
//特殊值处理,链表为空
// if(pHead == null){
// return null;
// }
// ListNode head0 = pHead;
// //创建一个哈希集合,存储对象为ListNode
// HashSet<ListNode> hashSet = new HashSet<>();
// //遍历链表,如果在哈希集合中存在该节点,即链表存在环;否则,将该节点添加到哈希集合中
// while (head0 != null){
// if(hashSet.contains(head0)){//哈希集合中存在该节点,该节点即为链表中环的入口节点,并返回该节点
// return head0;
// }else{//哈希集合中不存在该节点,将该节点添加到哈希集合中
// hashSet.add(head0);
// }
// head0 = head0.next; //节点移动
// }
// return null;
//方法二:利用快慢指针,运行时间大概是60ms
//特殊值处理,链表为空或者链表的长度为1
if(pHead == null || pHead.next == null){
return null;
}
ListNode fast = pHead.next.next; //初始化快指针
ListNode flow = pHead.next; //初始化慢指针
boolean flag = false; //标记值,如果为true代表是相遇后,反之,代表相遇前
while (flow != null && fast != null){ //遍历链表,当快慢指针都不为空时,
if(flow == fast){//如果快慢指针指向同一个节点,则代表有环
if(flag){//相遇后再次相遇,则此节点为链表环的入口节点
return flow;
}else{
fast = pHead;//相遇后,更新快指针指向头节点,满指针原地不动,此后快慢指针每次走一步
}
flag = true;
}else{//如果快慢指针不是指向同一个节点,更新快慢指针
if(flag){//相遇后,更新快指针指向头节点,满指针原地不动,此后快慢指针每次走一步
flow = flow.next; //慢指针每次走一步
fast = fast.next; //快指针每次走一步
}else{
flow = flow.next; //慢指针每次走一步
fast = fast.next; //快指针每次走两步
if(fast != null){//快指针每次走两步,可能存在刚走完一步就是空指针,所以要验证快指针为非空
fast = fast.next;
}
}
}
}
return null;
}
}