LeetCode Linked List Cycle && Linked List CycleII
2014-05-13 15:02
274 查看
Linked List Cycle:判断一个单链表是否有环,是返回true,不是则返回false。
典型的链表题,这题开始想用两个循环暴力遍历一番求出来,但超时,复杂度不是O(n),看看网上的解答原来可以这样:设置两个指针,一个慢指针,一个快指针,慢的一次走一个,快的走两个,这样如果有环的话,这两个指针必定会在环里开始绕,因为快指针相对于慢指针的速度是1,所以这两个指针必定会在环里的某个节点中相遇,所以只要判断两个是否相等就可以了。
代码:
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,即环的开始节点。
代码:
典型的链表题,这题开始想用两个循环暴力遍历一番求出来,但超时,复杂度不是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; } };