您的位置:首页 > 其它

142. linkedlist cycle

2016-07-03 11:23 302 查看
链表找环,以及环的入口的最经典做法。快慢指针法。快慢指针同时从开头出发,快指针每次走两步,慢指针每次走一步,如果会相遇,一定有环,当相遇时,将快指针重新移动到head,然后每次走一步,两指针再次相遇就是环的入口。



简单来说就是,head到入口距离为a, 入口到相遇为b, 相遇到入口为c, 这个是按照链表走向定的距离。然后我们可以得到,2*(a+b) = a + b + c + b; 所以a = c. 所以把快指针移动回head,每次走一步,会在入口相遇。

bool hasCircle(Node* head, Node* &encounter)
{
Node *fast = head, *slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
encounter = fast;
return true;
}
}
encounter = NULL;
return false;
}


注意:

1. 判空很重要,fast & fast->next, 因为fast保证开头有效,不用判断head为空的情况,保证fast->next不为空,就可以取fast->next->next。

2. 自身就是一个环,相遇点就是开头。需要判断下。

返回入口:

Node* findEntry(Node* head, Node* encounter)
{
Node *p1 = head, *p2 = encounter;
while(p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}


我的leetcode答案:

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
int cycle = 0;
while (fast && fast->next) { //判空很重要
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
cycle = 1;
break;
}
}
if (cycle == 1) {
if (fast == head) return head; // 判断是否自己就是个环
fast = head;
while (true) {
fast = fast->next;
slow = slow->next;
if (fast == slow) return fast;
}
}
else return NULL;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: