面試題——鏈表中環的入口節點

AcWing 34 鏈表中環的入口節點

題目

給定一個鏈表,若其中包含環,則輸出環的入口節點。

若其中不包含環,則輸出null

樣例

在這裏插入圖片描述

給定如上所示的鏈表:
[1, 2, 3, 4, 5, 6]
2
注意,這裏的2表示編號是2的節點,節點編號從0開始。所以編號是2的節點就是val等於3的節點。

則輸出環的入口節點3.

思路

​ 這道題解法很巧妙,有一股數學的氣息,首先我們回憶一下怎麼確定一個鏈表中是否存在環

​ 我們是使用快慢指針的方式來確定鏈表中是否存在環的,兩個指針onetwo都從鏈表的head出發,one每次走一個節點,two每次走兩個節點,如果鏈表存在環的情況下,兩個指針一定會在環中的某個位置相遇,否則如果two走到了鏈表結尾,說明鏈表沒有環

​ 那我們如何確定鏈表中環的入口節點呢?請看這張圖

在這裏插入圖片描述

​ 首先,我們假設入口節點b距離head節點a的距離爲x,兩個指針相遇的點c距離b點的長度是y,那麼,one指針走到b需要x步,而此時two指針已經走了2x步,正在環中某處(假設鏈表存在環),而當one再走y步就會到達兩個指針相遇的c點,再次期間,two同樣會走2y步,所以,在one到達b點時,two實際距離by步,也就是說,這個環的長度爲x + y,所以我們可以得到,當twoc點時,它距離b點差x

​ 通過這個結論,我們可以在兩個指針相遇時,讓one指回頭節點,此時one距離b點差x步,two距離b點也爲x步,從這個時候開始,我們讓兩個指針每次走一個單位,當兩個指針再次相遇時,這個點就是b點,代碼如下:

代碼

class Solution {
public:
    ListNode *entryNodeOfLoop(ListNode *head) {
		auto i = head, j = head;
		while (i && j) {
			i = i->next;
			j = j->next;
			if (j) {
				j = j->next;
				if (!j) return 0;
			}
			if (i == j) {
				i = head;
				while (i != j) {
					i = i->next;
					j = j->next;
				}
				return i;
			}
		}
		return 0;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章