问题描述(141):
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. If pos
is -1
, then there is no cycle in the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: true Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0 Output: true Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1 Output: false Explanation: There is no cycle in the linked list.
源码(141):
受到了剑指offer面试题23的启发(剑指offer总纲)。用了一个快慢指针,能相遇则说明有环,不能相遇而且最后到了NULL。说明没有。时间93%,空间100%。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head) return false;
ListNode *p1 = head, *p2 = head;
while(p1 && p2 && p2->next){
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2) return true;
}
return false;
}
};
问题描述(142):
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.
Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: tail connects to node index 1 Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0 Output: tail connects to node index 0 Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1 Output: no cycle Explanation: There is no cycle in the linked list.
源码(142):
还是受剑指offer23题的指导(剑指offer总纲)。定义两个快慢指针,快指针必定与慢指针在环中的某个点相遇。然后再让快指针循环,求出环的长度n。最后慢指针指向头部,快指针比慢指针快走n步,他两的相遇出就是环的起点。
时间94%,空间100%。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head) return NULL;
ListNode *p1=head, *p2=head;
// 找到环中任意一个顶点
while(p1 && p2 && p2->next){
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2) break;
}
if(!p1 || !p2 || !p2->next) return NULL;
// 确定环长度
int len = 1;
p2 = p2->next;
while(p2!=p1){
len++;
p2 = p2->next;
}
// 确定入口
p1 = p2 = head;
while(len--) p2 = p2->next;
// cout<<p2->val<<endl;
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
};
看到博客上一个大佬的写法:
则:相遇时
快指针路程=a+(b+c)m+b
慢指针路程=a+(b+c)n+b
其中b+c为环的长度,m为绕环的圈数(m>=1, n>0, m>n)。
快指针走的路程是慢指针的两倍,所以:
(a+(b+c)n+b)*2=a+(b+c)m+b
化简可得:
a=(m-n)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(m-n)圈环长度。其中m-n>0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
效率差不多,时间94%,空间100%,就是代码量少了很多:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head) return NULL;
ListNode *p1=head, *p2=head;
while(p1 && p2 && p2->next){
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2){
p2 = head;
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p2;
}
}
return NULL;
}
};