Description
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.
Follow up:
Can you solve it without using extra space?
分析
题目的意思是:找到一个链表的的环的起点,没有则返回NULL。
- 这同样是一个快慢指针的题目,先通过快慢指针判断是否有环,如果有环,则两个指针能够相遇,如果相遇,我们则把其中一个指针指向头结点,然后两个指针同时走,直到两个指针相遇,这样就得到了环的开始结点。
X,Y,Z分别为链表起始位置,环开始位置和两指针相遇位置,则根据快指针速度为慢指针速度的两倍,可以得出:
2*(a + b) = a + b + n * (b + c);即
a=(n - 1) * b + n * c = (n - 1)(b + c) +c
a+b 为慢指针走的步数,则2*(a+b)为快指针走的步数,快指针走的步数是慢指针的2倍,b+c为环的长度
注意到b+c恰好为环的长度,故可以推出,如将此时两指针分别放在起始位置和相遇位置,并以相同速度前进,当一个指针走完距离a时,另一个指针恰好走出 绕环n-1圈加上c的距离。
故两指针会在环开始位置相遇。
C++实现
/**
* 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* slow=head;
ListNode* fast=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}
};
Python实现
- fast走的步数是slow的2倍,即f=2s.
- fast比slow多走了f= s+nb
所以s=nb,f=2nb,如果让指针从链表头部一直向前走并统计步数k,那么所有 走到链表入口节点时的步数 是:k=a+nb
现在s走了nb,则想办法让它走a步就能走到入口位置。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return None
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
pre = head
while pre != slow:
pre = pre.next
slow = slow.next
return pre
return None
下面的版本跟上面的思路一样:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if not head or not head.next:
return None
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow==fast:
break
if slow!=fast:
return None
pre =head
while pre!=slow:
pre = pre.next
slow = slow.next
return pre