leetcode OJ 判斷單鏈表中是否有環
阿新 • • 發佈:2019-02-01
題目:判斷單鏈表中是否存在環
Binary Tree Preorder Traversal
單鏈表的結構體為:
struct NodeList
{
int val;
NodeList *next;
NodeList(int x) : val(x),next(NULL){}
};
思路很簡單,就是搞兩個指標,初始值均指向連結串列頭,但是一個跑的快,一個跑的慢。如果連結串列中沒有環,兩個指標不會相遇,如果有環的話,則一定會相遇(慢的被套圈了)。
這裡我們定下快指標一次走兩步,慢指標一次走一步。由於快指標每次追慢指標一格,快慢指標間最大距離<環長(快指標剛過環入口,慢指標進來了),所以在慢指標第一次走完環長之前,快指標必然能追上它(此處為後面做鋪墊)。
判斷有否存在環的演算法,思路有了很簡單:
bool hasCircle(NodeList *head)
{
NodeList *fast=head;
NodeList *slow=head;
while(fast!=NULL&&fast->!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow) return true;
}
return true;
}
看了看大牛寫的題目擴充套件,一般還要求找出環入口的位置,
思路是這樣的:
假設相遇時慢指標走了s,則快指標走了2s,兩者的差s必然為環長的n倍,即s=nl(l為環長),即如果一個指標S1從連結串列頭出發,另一個指標S2從相遇點出發(兩者速度相同),S1走到S2出發點時兩者一定會相遇(兩者都走了nl),而他們的速度是一樣的,說明他們在環入口處其實就相遇了,而且是第一次相遇(就在一起了~~~~),這樣我們就能定位到環入口了。
有了思路程式碼也很簡單(環已經存在):
另外,大牛還引申了“如何判斷兩個無環單鏈表是否相交”:運用判斷單鏈表環的想法,將其中一個連結串列首尾相連,然後判斷另一個是否有環,若有環則說明兩連結串列相交。NodeList* findCircleEnter(NodeList* head) { NodeList *fast=head; NodeList *slow=head; while(fast!=NULL&&fast->!=NULL) { fast=fast->next->next; slow=slow->next; if(fast==slow) break; } slow=head; while(slow!=head) { slow=slow->next; fast=fast->next; } return slow; }
附上鍊接:
http://www.cppblog.com/humanchao/archive/2012/11/12/47357.html