题目:
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?
代码:
使用hashmap版
/** * 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) { std::map<ListNode *, bool> ifNodeOccured; ListNode *p = head; while ( p ) { if ( ifNodeOccured.find(p) != ifNodeOccured.end() ) return p; ifNodeOccured.insert(std::pair<ListNode *, bool>(p,true)); p = p->next; } return NULL; } };
不用hashmap版(O(1)空间复杂度)
/** * 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) return false; ListNode *p1 = head; ListNode *p2 = head; while ( p2->next && p2->next->next ) { p2 = p2->next->next; p1 = p1->next; if (p2==p1) { p1 = head; while (p1 != p2) { p1 = p1->next; p2 = p2->next; } return p1; } } return false; } };
Tips:
个人还是喜欢hashmap的解法,因为比较统一;但当数据量很大的时候,开辟hashmap占用的资源也是蛮多的。
第二种解法参考的如下两篇日志:
http://www.cnblogs.com/hiddenfox/p/3408931.html
http://blog.csdn.net/cs_guoxiaozhu/article/details/14209743
这里只讨论有环的case:
快慢指针技巧;慢==快,则快走的路程是慢走的路程的2倍;再让慢从头走,快从相遇点走,但每次改走一步,则再次相遇的地方就是起点。
这个无论是head到相遇点多长,都满足,算是一个特殊的技巧吧。还是很喜欢hashmap的做法。
====================================================
第二次过这道题,大体思路还记得。hashmap的方法一次写出来AC了,特殊技巧的写法参照了之前的代码。
/** * 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) return head; ListNode* p1 = head; ListNode* p2 = head; while (p2) { p1 = p1->next; p2 = p2->next; if (p2) { p2 = p2->next; } else { return NULL; } if ( p1==p2 ) { p1 = head; while (p1!=p2) { p1 = p1->next; p2 = p2->next; } return p1; } } return NULL; } };
这里有个细节,需要记住:当p1=p2的时候,重置p1=head;接下来先要判断p1!=p2然后再开始走,否则,当整个链表是个环的时候,就出bug了。