判斷單鏈表中有沒有環,如果有找到環的入口節點。
三個問題:
1、如何確定鏈表中包含環:兩個指針,一個指針一次走一步,一個指針一次走兩步。如果走得快的指針追上了走得慢的指針,則說明鏈表包含環; 如果走得快的指針走到了鏈表末尾(p->next == NULL)都沒有追上第一個指針,則無環。
2、如何找到環的入口:定義兩個指針p1,p2指向頭結點,如果環有n個結點, 則p1先移動n步,然後兩個指針以相同的速度向前移動。當p2指向環的入口節點時,p1已經圍繞着環走了一圈又回到了入口節點。
3、如何得到環中節點數目:1中相遇的兩個指針指向的結點一定在環中,可以從這個節點出發,一邊繼續移動一邊計數,當再次回到這個節點時,就可以得到環中節點數了。
//判斷鏈表內是否包含環
//找到快慢指針相遇的節點,此節點必定在環內
ListNode* meetingNode(ListNode* head){
if(head == NULL)
return NULL;
ListNode* slow = head->next;
if(slow == NULL)
return NULL;
ListNode* fast == slow->next;
while(fast != NULL && slow != NULL){
if(fast == slow)
return fast;
slow = slow->next;
fast = fast->next;
if(fast != NULL)
fast = fast->next;
}
return NULL:
}
//得出環中節點數目,並找到環的入口節點
ListNode* EntryNodeOfLoop(ListNode* head){
ListNode* meetingNode = meetingNode(head);
if(meetingNode == NULL)
return NULL;
//找到環中節點數目
int nodesInLoop = 1;
ListNode* m = meetingNode;
while(m->next != meetingNode){
m = m->next;
nodesInLoop++;
}
m = head;
for(int i=0; i<nodesInLoop; ++i){
m = m->next;
}
ListNode* n = head;
while(m != n){
m = m->next;
n = n->next;
}
return m;
}