给定一个链表,如果链表中存在环,则返回到链表中环的起始节点的值,如果没有环,返回null。
您在真实的面试中是否遇到过这个题?
Yes
样例
给出 -21->10->4->5, tail connects to node index 1,返回10
挑战
标签
Expand
不使用额外的空间
相关题目 Expand
分析:首先肯定可以利用快慢指针来判断该链表中有没有环,如果快慢指针能够遇到,那么肯定存在环,那么完全可以把环打破,变成求两个链表的第一个交叉点问题,也是有O(n)且不消耗空间的解法的。
代码:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The node where the cycle begins.
* if there is no cycle, return null
*/
ListNode *detectCycle(ListNode *head) {
// write your code here
if(head == nullptr)
return nullptr;
ListNode*fast = head;
ListNode*slow = head;
while(true)
{
if(fast&&fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast==slow)
{
ListNode*pre = findPreNode(slow);
pre->next = nullptr;
ListNode*ret = findFirstIntersect(head,slow);
return ret;
}
}
else
{
return nullptr;
}
}
}
ListNode*findPreNode(ListNode*node)
{
ListNode*temp = node;
while(temp->next!=node)
temp = temp->next;
return temp;
}
ListNode*findFirstIntersect(ListNode*head1,ListNode*head2)
{
int len1 = 0;
ListNode*temp1 = head1;
while(temp1){len1++;temp1=temp1->next;}
int len2 = 0;
ListNode*temp2 = head2;
while(temp2){len2++;temp2=temp2->next;}
if(len1>len2)
{
int k = len1-len2;
while(k--)
head1 = head1->next;
}
else
{
int k = len2-len1;
while(k--)
head2 = head2->next;
}
while(head1!=head2)
{
head1 = head1->next;
head2 = head2->next;
}
return head1;
}
};