三類(lèi)情況:
1岖瑰、遇到這個(gè)問(wèn)題,首先想到的是遍歷鏈表砂代,尋找是否有相同地址蹋订,借此判斷鏈表中是否有環(huán)。
listnode_ptr current =head->next;
while(current)
{
if(current==head)
{
printf("有環(huán)刻伊!\n");
return 0;
}
else
{
current=current->next;
}
}
printf("無(wú)環(huán)露戒!\n");
return 0;
這段代碼滿(mǎn)足了(1)(鏈表無(wú)環(huán))、(2)(鏈表頭尾相連)兩類(lèi)情況娃圆,卻沒(méi)有將(3)情況考慮在內(nèi)玫锋,如果出現(xiàn)(3)類(lèi)情況,程序會(huì)進(jìn)入死循環(huán)讼呢。
2撩鹿、將(3)考慮在內(nèi),首先想到我們可能需要一塊空間來(lái)存儲(chǔ)指針悦屏,遍歷新指針時(shí)將其和儲(chǔ)存的舊指針比對(duì)节沦,若有相同指針,則該鏈表有環(huán)础爬,否則將這個(gè)新指針存下來(lái)后繼續(xù)往下讀取甫贯,直到遇見(jiàn)NULL,這說(shuō)明這個(gè)鏈表無(wú)環(huán)看蚜。
上述方法雖然可行叫搁,可是否還有更簡(jiǎn)便的算法?
3供炎、假設(shè)有兩個(gè)學(xué)生A和B在跑道上跑步渴逻,兩人從相同起點(diǎn)出發(fā),假設(shè)A的速度為2m/s音诫,B的速度為1m/s,結(jié)果會(huì)發(fā)生什么惨奕?
答案很簡(jiǎn)單,A繞了跑道一圈之后會(huì)追上B竭钝!
將這個(gè)問(wèn)題延伸到鏈表中梨撞,跑道就是鏈表,我們可以設(shè)置兩個(gè)指針香罐,a跑的快卧波,b跑的慢,如果鏈表有環(huán)穴吹,那么當(dāng)程序執(zhí)行到某一狀態(tài)時(shí)幽勒,a==b。如果鏈表沒(méi)有環(huán)港令,程序會(huì)執(zhí)行到a==NULL啥容,結(jié)束。
listnode_ptr fast=head->next;
listnode_ptr slow=head;
while(fast)
{
if(fast==slow)
{
printf("環(huán)顷霹!\n");
return 0;
}
else
{
fast=fast->next;
if(!fast)
{
printf("無(wú)環(huán)咪惠!\n");
return 0;
}
else
{
fast=fast->next;
slow=slow->next;
}
}
}
printf("無(wú)環(huán)!\n");
return 0;
4淋淀、關(guān)于算法復(fù)雜度:
如圖遥昧,鏈表長(zhǎng)度為n,環(huán)節(jié)點(diǎn)個(gè)數(shù)為m朵纷,則循環(huán) t=n-m 次時(shí)炭臭,slow進(jìn)入環(huán)中,此時(shí)袍辞,我們假設(shè)fast與slow相距x個(gè)節(jié)點(diǎn)鞋仍,那么,經(jīng)過(guò)t'次循環(huán)搅吁,二者相遇時(shí)威创,有:
2t'=t'+(m-x) -> t'=m-x -> t'<=m.
因此,總共循環(huán)了T=t+t' <= n. 算法復(fù)雜度為O(n).