您的位置:首页 > 其它

LeetCode-Linked List Cycle II

2015-08-01 15:04 399 查看
题目:LeetCode-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?

解释:

做了1就忍不住要做2,这道题要求高了一点。要返回开始循环的节点,那么你肯定得找到这个节点。怎么找?循环链表中,有且只有两个节点的指针域是相同的,并且相同的两个指针就是指向循环开始的节点的,所以可以根据这一点来寻找循环链表的开始节点。

要实现这个要求,有一个比较直接的方法,即逐个比较法。就是用两个指针,一个在循环部分不断的循环(指针 fast),一个从链表的头指针开始移动(指针slow),slow每移动一次,fast 移动一圈,依次比较他们是否相同(虽然感觉这样的时间负责度会很大,但这总比不做好吧)。实现代码如下:

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow, *fast;
ListNode  *p = NULL;
slow = fast = head;
while(1)
{
if(fast == NULL || fast->next == NULL )
return NULL;
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
p = slow;  //记录当前节点,作是否循环一圈的判断
slow = head;
while(1)
{
if(slow == fast) return slow;
fast = fast->next;
if(fast == p)
{
slow = slow->next; //当fast回到P处
//时,即循环完了一圈,此时slow移动一位.
}
}
}
}

}
};


运行,程序通过,不过果然,运行时间72Ms,离系统记录的12Ms还差很多,这时就要改进代码了。

再仔细观察一下循环链表的特点,发现在一个循环链表中,快慢指针相遇的点总是固定的某点,如图中的3处,因为快指针一定要比慢指针快了一圈,它们才有可能相遇。再假设它们是完全循环链表,那么它们相遇点肯定是第一个节点,那么非完全循环链表为什么不是相遇在开始的节点处呢?因为它事先跑了一段无关的路了呀(图中的1~2段),也正是因为它们跑了一段路了,所以相当于它们在3处开始移动的,也就是说明了什么?说明1~2段和2~3段的路程是相同的!!所以一个指针从链头开始,一个指针从相遇处开始,同步移动,它们必然会在循环开始处相遇,这样也就找出来题求的节点了。



代码如下:

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow, *fast;
ListNode  *p = NULL;
slow = fast = head;
while(1)
{
if(fast == NULL || fast->next == NULL )
return NULL;
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
slow  = head;
while(1)
{
if(slow == fast) return slow;
slow = slow->next;
fast = fast->next;
}
}
}

}
};


运行用时12Ms。这是完全自己写的代码,还没看大神们的代码,不知是否相同。虽然思考这道题时用了不少时间,但看到自己的代码被access时,觉得还是值得的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LeetCode Linked Cycle