您的位置:首页 > 其它

leetcode之Linked List CycleII

2014-04-02 20:23 330 查看
原题如下:

思路:此题共分两个步骤,首先是判断是否有环,然后是在有环的基础上判断环的入口地址。

判断是否有环:利用两个节点指针,首先分别指向头结点,然后让其中一个指针每次走两步(快指针),让另一个指针每次走一步(慢指针),当两个指针能够相遇,则说明链中有环,否则无环。此原理如下:

若链中有环,则两个指针都能够进入环中,根据运动的相对性,在进入环后,可以假设满指针静止,快指针每次走一步,则两指针在环中必能相遇。

判断环入口:假设环外边的链长L,环长R,以慢指针进入环开始计时,当两个指针第一次相遇时,假设慢指针在环中走了x步,则有:

(2*(L+x)-L)%R = x%R,即(L+x)%R = 0.此时,再另慢指针指向链的起始位置,快指针在相遇位置(此时距换入口位置x%R)以每次一步向前走,当慢指针再次来到换入口时(即慢指针走了L步),快指针也向前走了L步,其相距换入口位置(x+L),由于(x+L)%R = 0,所以快指针也来到了环的入口处,而且可以肯定这是两指针重置后的第一次相遇(由于慢指针刚计入环),且刚好在环的入口处,所以利用此方法可以找到环的入口。

代码如下:

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
ListNode *detectCycle(ListNode *head) {

if(head == NULL || head->next == NULL)
return NULL;
ListNode *p1 = head;
ListNode *p2 = head;//一定让快慢两指针初值都指向第一个结点,否则会出现意想不到的错误
while(p2 != NULL && p2->next != NULL){
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2)
break;
}
if(p1 != p2)
return NULL;
p1 = head;
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: