链表是否有环
Posted eimadrigal
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表是否有环相关的知识,希望对你有一定的参考价值。
一、在O(1)的空间复杂度内判断单链表是否有环
题目描述
快慢指针:若链表有环,则两指针必在将来某一时刻相遇:
假设环的长度为(L),快指针距离环的入口距离为(S),慢指针在入口,则经过(t)时间相遇,有:
(S+2t-t=nL),即:(S+t=nL),又(S<L),故取(n=1, t=L-S),即慢指针在一圈内必能遇到快指针。
//单链表定义
struct ListNode{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL) {}
};
class Solution {
public:
bool hasCycle(ListNode* head)
{
if (head == NULL)
return false;
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
return true;
}
return false;
}
};
二、O(1)空间复杂度返回环的入口,若无环,返回NULL
题目描述
设链头距离环的入口距离为(s_1),相遇点距离入口距离为(s_2),环的长度为(L),则快慢指针走过的路程是2倍关系:
[2(s_1+s_2)=nL+s_1+s_2]
相遇前快指针已经绕了(n)圈,化简:
[s_1=nL-s_2]
1,(n=1),则(s_1=L-s_2);
2,(n>1),则(s_1=L-s_2+(n-1)L)。
也就是说:设两个指针(p_1, p_2),(p_1)指向链头,(p_2)指向相遇点,每次都走一步,则两指针必在环的入口相遇。
//单链表定义
struct ListNode{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL) {}
};
class Solution{
public:
ListNode* detectCycle(ListNode* head)
{
auto fast = head;
auto slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
break;
}
if(!fast || !fast->next) //无环,fast走到尽头
return nullptr;
slow = head; //一个指向链头,另一个指向相遇点
while(slow != fast)
{
fast = fast->next;
slow = slow->next;
}
return slow; //找到入口
}
};
以上是关于链表是否有环的主要内容,如果未能解决你的问题,请参考以下文章