這個問題在面試中是老生常談的問題了,而且,解決這類問題的主要方法就是追擊法,因此,這篇部落格中只講解這種方法求解環的問題。
這裡給出三個鍊錶中環的問題:
這裡給出一副,所有的討論都在這上進行。
這個問題很好解決,設定兩個指標ptr_1, ptr_2
在a處,讓ptr_1
以1的速度往後走(即每次移動乙個位置),ptr_2
以2的速度往後走,如果鍊錶中存在環,那麼ptr_1, ptr_2
都會進入環中,ptr_2
會以2的速度追擊ptr_1
,而且ptr_2
一定可以追上ptr_1
(即ptr_2 == ptr_1
);如果鍊錶中不存在環,那麼ptr_1
和ptr_2
之中一定有乙個等於空指標。
bool judge_the_circle(listnode *phead)
return ptr_1 != nullptr && ptr_1 == ptr_2;
}
還是上面那幅,問題一中講到如果有環,ptr_1
和ptr_2
一定會相遇,但是相遇在哪個地方呢?是不是沒有思考過這個問題,要想知道相遇在哪個地方,還要從這兩個指標的速度入手。
與上個問題一樣的做法,只不過這次我要分一下運動的階段了:
上面數學分析的既是演算法的原理,也是演算法的步驟,因此可以很清楚地寫出**。
listnode* entrynodeofloop(listnode* phead)
while (ptr_1
!= nullptr && ptr_2
!= nullptr &&
ptr_2
->
next
!= nullptr && ptr_1
!= ptr_2);
if (!(ptr_1
!= nullptr && ptr_2
!= nullptr && ptr_2
->
next
!= nullptr))
return
nullptr;
for (ptr_1 = phead; ptr_1
!= ptr_2; ptr_1 = ptr_1
->
next, ptr_2 = ptr_2
->
next) {}
return
ptr_1;
}
理解了問題二,這個問題就很簡單了,呼叫問題二的函式,求出環的入口,然後讓ptr_1
走到環的入口,然後讓ptr_1
再次走到環的入口,統計下路程,就是環長。
int lengthofloop(listnode* phead)
while ((ptr = ptr->next) != enternode);
return ret;
}
這類問題慢慢分析就好了,多畫圖。 關於鍊錶追趕 鍊錶中環的問題
關於環的問題,介紹幾個個經典的題目 1.求鍊錶倒數第k個結點 最經典,最常見的解法就是,設定兩個指標p1,p2,一開始分別指向頭結點,首先p2先移動k個節點,之後開始p1,p2每次移動1個節點,直到p2達到最後乙個節點位置,那麼p1指向的就是倒數第k個節點。不過這種解法主要是針對單鏈表,且鍊錶中不存...
鍊錶 尋找鍊錶中環的起點
給定乙個單鏈表,若該鍊錶有環,返回環的起點,若沒有,返回null 基本思路 每遇到乙個節點,計數器 當遇到訪問次數為2時,返回該節點,否則在迴圈結束前還沒有找到,則返回null class solution return null 高階思路 雙指標思路,證明 慢指標速度為v 那麼快指標速度為2v 第...
鍊錶 鍊錶中環的入口結點
給乙個鍊錶,若其中包含環,請找出該鍊錶的環的入口結點,否則,輸出null。知識點回顧 快慢指標 思路 使用快慢指標 假設有p,q兩指標,p每步跨乙個結點,q每步跨兩個結點。那麼經過k步之後q比p多走過的結點數為k。如果鍊錶中沒有環,那麼q永遠在p的前面,兩指標不會相遇。如果鍊錶有環,且環中結點個數為...