链表中环的入口节点
java:
解释
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) return null;
ListNode first = head, second = head;//注!!first和second需要同时从head走
while (true) {
first = first.next;
if (second == null || second.next == null)
return null;
second = second.next.next;
if (first == second)
break;
}
first = head;
while (first != second) {
first = first.next;
second = second.next;
}
return first;
}
}
//考虑三种情况:(1)链表是空的;(2)链表只有一个<这两种情况都不可能有环返回null>;(3)链表没有环在下面一步循环结束考虑return NULL;
//两个指针指向头,然后pFast移两步,pSlow移一步,如果相等就能知道有无环。<pFast->next是空的时候说明无环返回NULL>;
//继续在相遇的节点pFast指针移动,count记数pFast = pSlow时,知道环的节点数字<法一没有这步>;
//一个指针指向头,一个不动,两个指针都每次移动一位相遇节点就是入口;
//法一
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode *pFir = pHead, *pSec = pHead;
while (pSec && pSec->next) {//注!!!pSec不能在最后一节点并且不能在最后的NULL节点
pFir = pFir->next;
pSec = pSec->next->next;
if (pFir == pSec) break;
}
if (!pSec || !pSec->next) return NULL;
pFir = pHead;
while (pFir != pSec) {
pFir = pFir->next;
pSec = pSec->next;
}
return pFir;
}
};
//法二
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead){
if(FindLoopNode(pHead)){
ListNode* pFast = FindLoopNode(pHead), *pSlow = FindLoopNode(pHead);
int count = 0;//算出环中有几个节点
while(pFast != pSlow){
pFast = pFast->next;
++count;
}
pSlow = pHead;//一个指针指向头节点,一个间隔count个节点,
for(int i = 0; i < count; i++){
pFast = pSlow->next;
}
//相遇时候返回链表入口
while(pFast != pSlow){
pFast = pFast->next;
pSlow = pSlow->next;
}
return pFast;
}
else{
return NULL;
}
}
private:
ListNode* FindLoopNode(ListNode* pHead){//判断单链表中有没有环,有环返回相遇节点
if(pHead == NULL || pHead->next == NULL) return NULL;
ListNode* pFast = pHead, *pSlow = pHead;
while(pFast != NULL && pFast->next != NULL){
pFast = pFast->next->next;
pSlow = pSlow->next;
if(pFast == pSlow){
return pFast;
}
}
return NULL;
}
};