链接:
题意:
求链表是否有环,并给出入环的点
解:
哈希关联标记或者快慢指针
快慢指针逻辑:设入环前长度a,快慢相遇时指针在b,环长度为c,fast=2*slow(慢走一步,快走两步)
那么当相遇时2(a+b)=a+nc+b
==>a=nc-b=(n-1)c+c-b
(fast已经走了n圈)
如果有新的指针ptr
以速度1走完a到达入环位置,则slow在期间移动了(n-1)c+c-b
,其中(n-1)c
刚好为n-1圈被忽略,b+c-b=c
,刚好又走完一圈到达入环节点
所以这时如果ptr和slow相遇,则该节点为入环位置,如果不相遇或者过程中任意一个指针指向空节点则不存在环
主要是数学推导,有点难
实际代码:
#include<bits/stdc++.h>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode *detectCycle(ListNode *head)//快慢指针
{
if(head==nullptr||head->next==nullptr) return nullptr;
ListNode* fast=head,*slow=head;
slow=slow->next;fast=slow->next;
while(slow!=fast&&slow!=nullptr&&fast!=nullptr)//快慢指针相遇
{
slow=slow->next;
fast=fast->next;
if(fast!=nullptr) fast=fast->next;
}
if(fast==nullptr) return NULL;
fast=head;//新指针ptr
while(slow!=fast&&slow!=nullptr&&fast!=nullptr)//寻找入环点
{
slow=slow->next;
fast=fast->next;
}
if(slow==fast&&slow!=nullptr) return slow;
return NULL;
}
/*
ListNode *detectCycle(ListNode *head)//哈希map
{
unordered_map<ListNode*,bool>book;
if(head==nullptr) return nullptr;
while(head!=nullptr)
{
if(book.count(head)) return head;
else book[head]=true;
head=head->next;
}
return nullptr;
}*/
int main()
{
}
限制:
- 链表中节点的数目范围在范围
[0, 104]
内 -105 <= Node.val <= 105
pos
的值为-1
或者链表中的一个有效索引