import java.util.HashMap;
import java.util.Map;
/**
* 链表中环的入口结点
*
* 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
*/
public class JZ055TheEntryNodeOfALinkInALinkedList {
/**
* Map存储
* @param pHead
* @return
*/
public ListNode EntryNodeOfLoop(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return null;
}
Map<ListNode, Integer> map = new HashMap<>();
while (pHead != null) {
if (!map.containsKey(pHead)) {
map.put(pHead, 1);
} else {
return pHead;
}
pHead = pHead.next;
}
return null;
}
/**
* 快慢指针
* @param pHead
* @return
*/
public ListNode EntryNodeOfLoop2(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return null;
}
ListNode meetNode = listNodeInCircle(pHead);
if (meetNode != null) {
ListNode first = pHead;
ListNode second = meetNode;
while (first != second) {
first = first.next;
second = second.next;
}
return first;
}
return null;
}
/**
* 断链法
* 1、断链法,可以改变原有链表结构时,可使用该方法
* 2、两指针遍历链表,一个起始指向第二个节点,另一个指向头节点,后一个指针一直断链,并依次推进两个指针,当前一个指针为null时,后一个指针会指向环的入口节点
* 总结:不知道为什么提交代码的时候不用判断有没有环,理解上没有环,最后返回的是最后一个节点
* @param pHead
* @return
*/
public ListNode EntryNodeOfLoop3(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return null;
}
ListNode meetNode = listNodeInCircle(pHead);
if (meetNode != null) {
ListNode slow = pHead;
ListNode fast = pHead.next;
while (fast != null) {
slow.next = null; // 断链法
slow = fast;
fast = fast.next;
}
}
return null;
}
private ListNode listNodeInCircle(ListNode pHead) {
ListNode oneStep = pHead;
ListNode twoStep = pHead;
while (oneStep != null && twoStep != null && twoStep.next != null) {
twoStep = twoStep.next.next;
oneStep = oneStep.next;
if (twoStep == oneStep) {
return oneStep;
}
}
return null;
}
/*
总结:
链表中环的入口结点 上述第三种方法,即断链法不起作用了 {},{1}
*/
}