LeetCode Linked List Cycle && Linked List CycleII

来源:互联网 发布:php登录成功显示用户名 编辑:程序博客网 时间:2024/06/08 03:25

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;    }};


0 0
原创粉丝点击