您的位置:首页 > 其它

判断一个链表是否有环,如果有环返回环开始的结点指针

2014-04-10 16:44 357 查看
LeetCode OJ :Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return 
null
.

Follow up:Can you solve it without using extra space?

/**
* Definition for singly-linked list.
* 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 *p, *q;
p = q = head;

p = p->next;
q = q->next->next;

//指针追击问题
while((q != NULL) && (q->next != NULL) && (p != q))
{
p = p->next;
q = q->next->next;
}
if((q == NULL) || (q->next == NULL))
return NULL;
else if(p == q)     //链表肯定存在环
{
int flag = 0;
ListNode *r, *first;
r = head;

if((r == p) || (r == q))    //只包含头结点的环
return r;

if(p->next == q->next->next)//只包含尾结点的环
return p;

while((p != r) && (q != r))
{
p = p->next;
q = q->next->next;

while(p != q)
{
if((p == r) || (q == r))
return r;

p = p->next;
q = q->next->next;
}
r = r->next;

if((r == p) || (r == q))
return r;
}

}

}
};

看到一个更牛叉的解法:这实际上是一个经典的龟兔赛跑问题。

假设:

x:环开始的索引结点
y:环的长度
兔的赛跑速度是龟的两倍
这样兔肯定在环内的某一点上追上龟,假设这一点为m

这样如果设龟走过的总路程为:x+ky+m,兔走过的总路程为:x+ty+m。则有:

x+ty+m = 2(x+ky+m)
故有:x+m = (t-2k)y。所以(x+m)mod y = 0,所以有如下方法:

让快指针停在两指针相遇的点,然后让慢指针回到头指针的位置,两个指针同时出发,每次走一步。

当慢指针走到环的第一个结点处(即走了x步),此时快指针距离环的第一个结点的位置为:x+m,即也在环的第一个结点处。所以此时两个指针又相遇了。

这样就可以判定环的第一个结点的位置了,即,两指针相遇的位置!

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
ListNode* slow = head;
ListNode* fast = head;
do{
if( !slow || !fast ) return NULL;
slow = slow->next;
fast = fast->next;
if( fast ) fast = fast->next;
else return NULL;
}while( slow != fast );
slow = head;
while( slow != fast ){
slow = slow->next;
fast = fast->next;
}
return slow;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐