您的位置:首页 > 其它

LeetCode Linked List Cycle && Linked List CycleII

2014-05-13 15:02 274 查看
Linked List Cycle:判断一个单链表是否有环,是返回true,不是则返回false。

典型的链表题,这题开始想用两个循环暴力遍历一番求出来,但超时,复杂度不是O(n),看看网上的解答原来可以这样:设置两个指针,一个慢指针,一个快指针,慢的一次走一个,快的走两个,这样如果有环的话,这两个指针必定会在环里开始绕,因为快指针相对于慢指针的速度是1,所以这两个指针必定会在环里的某个节点中相遇,所以只要判断两个是否相等就可以了。

代码:

class Solution {
public:
bool hasCycle(ListNode *head) {
if(head == NULL)return false;
ListNode * slow = head, * fast = head;
while(fast != NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast)return true;
}
return false;
}
};







Linked List Cycle II:判断一个链表中是否有环,如果有则返回该环的开始节点,没有则返回NULL。这题可以延用上题的思想,同样是快慢指针,我们可以画张图来看一下.



X为链表首节点,Y为环开始节点,Z为两个指针第一次相遇时的节点,在相遇前,设(a-c) = A, (c-d) = B, (d-c) = C。不考虑绕圈,slow走过的距离为A+B,fast走过的距离为A+B+C+B 因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,有 2(A+B) = A+B+C+B,可以得到A=C(这个结论很重要!)。所以我们可以在两个指针相遇后, 将fast从X出发, slow从Z出发,两个指针每次走一步,相遇的节点就是Y,即环的开始节点。
代码:

class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head)return head;
ListNode * slow = head;
ListNode * fast = head;
while(true){
if(!fast || !fast->next)return NULL;
slow = slow->next;
fast = fast->next->next;
if(slow == fast)break;
}
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: