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;
}
复制代码