Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to.node
If pos is -1, then there is no cycle in the linked list.git
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
複製代碼
代碼以下:github
bool hasCycle(struct ListNode *head) {
int impossibleNum = INT_MIN + 55467;
while (head != NULL) {
if (head->val == impossibleNum) {
return true;
}
head->val = impossibleNum;
head = head->next;
}
return false;
}
複製代碼
思路參考,用字典,用ListNode的address做爲key,每走一個ListNode判斷該node的address是否在字典內,若是鏈表走到底則沒有cycle,不然則有cycle(且第一個遇到的爲cycle的head)bash
因爲c的標準庫沒有dictionary(reference),此處代碼略ide
思路二解釋:從head node開始,一個指針一次走一個node,另外一個一次走兩個node,,若是二者可以相遇,則證實有cycleoop
常識來想很簡單,兩我的在操場跑步,一我的跑的速度是另外一我的的2倍,他們初始位置不限制;但慢的人跑一圈,快的會跑兩圈,他們確定會在某處相遇ui
證實:idea
問題能夠等價爲:對於cycle裏任意兩個node(節點),一個以1倍速同方向走,一個以2倍速同方向走,最終必定相遇;
設cycle長爲l(l>0),k爲兩node初始距離(-l < k < l)
問題可視爲 2x % l = (x + k) % l ,在 x > 0 狀況下必定有解
即 2x = x + k + m * l (m可謂任意正整數) 在 x > 0 狀況下有解
顯然,
當k < 0時,令m = 1, 即x = l + k;爲其中一個解,
當k >= 0 時,x = k, 爲其中一個解;
複製代碼
代碼:spa
bool hasCycle(struct ListNode *head) {
if (head == NULL) {
return false;
}
struct ListNode *pSlow = head;
struct ListNode *pFast = head;
while (pSlow->next != NULL && pFast->next != NULL && pFast->next->next != NULL) {
pSlow = pSlow->next;
pFast = pFast->next->next;
if (pSlow == pFast) {
return true;
}
}
return false;
}
複製代碼
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.指針
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Follow-up: Can you solve it without using extra space?
Do not modify the linked list
和Can you solve it without using extra space?
,q141思路一不適用,考慮q141思路二上作文章;可是,如何拿到cycle的headnode?
設cycle前node集爲pre,pre長度爲p,cycle長爲l,相遇節點爲cycle的第k個node,相遇時慢指針pSlow走的步數爲total。
則有:
①2total = p + k + m * l (m ∈ Z)
②total = p + k + n * l (n < m, n 屬於 Z)
① - ②得 ③total = (m - n) * l
可得p + k = (m - 2n) * l
複製代碼
p + k 是 l的倍數,如何使用該條件獲得loopHead?
咱們知道,當咱們快慢指針相遇時,咱們當前的節點位置爲k,那麼讓慢指針k再走p個節點,必定爲loopHead節點。
但如何走一個p節點?
brilliant idea:再讓一個慢指針從head節點走,兩指針第一次相遇,則二者走了p節點!且該節點就是要求的cycle的headnode!!!
複製代碼
參考圖:
struct ListNode *detectCycle(struct ListNode *head) {
if (head == NULL) {
return head;
}
struct ListNode *pSlow = head;
struct ListNode *pFast = head;
bool isCycle = false;
while (pSlow->next != NULL && pFast->next != NULL && pFast->next->next != NULL) {
pSlow = pSlow->next;
pFast = pFast->next->next;
if (pSlow == pFast) {
isCycle = true;
break;
}
}
if (isCycle) {
pFast = head;
while (pFast != pSlow) {
pFast = pFast->next;
pSlow = pSlow->next;
}
return pFast;
}
return NULL;
}
複製代碼