leetcode之Linked List CycleII

来源:互联网 发布:梅花泪网络歌手 编辑:程序博客网 时间:2024/06/08 12:19

原题如下:



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

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

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

判断环入口:假设环外边的链长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;}};


0 0
原创粉丝点击