Given a linked list, determine if it has a cycle in it.
Follow up: Can you solve it without using extra space?
"Time Limit Exceeded"费时间的方法如下:查看p结点与它之前的结点t是否有连接;p往前挪一个结点,则t都要从head开始遍历到p。
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: bool hasCycle(ListNode *head) { if(head == NULL) return false; ListNode *p = head; while(p != NULL) { if(p->next == p) return true; ListNode *t = head; while(t != p) { if(p->next == t) return true; else t = t->next; } p = p->next; } return false; } };
Accept的方法如下:指针p每次往前走2步,指针t每次往前走1步,如果有循环,则p总会与t在第二圈相遇,虽然相遇点不一定是环的循环连接点。
class Solution { public: bool hasCycle(ListNode *head) { if(head == NULL) return false; ListNode *p = head,*t=head; while(p!=NULL) { if(p->next != NULL )//判断是否到达末点或者是否存在自循环。 { if( p==p->next) return true; } else return false; p = p->next; if(p == t) return true; if(p->next != NULL ) //判断是否到达末点或者是否存在自循环。 { if( p==p->next) return true; } else return false; p=p->next; if(p == t) return true; t = t->next; } } };
还有一种使用set<ListNode *>来记录每个结点的指针,然后p开始单步走,判断结点如果已经存在set里,表明有循环。但此种方法使用的空间是O(n),超出要求:
class Solution { public: bool hasCycle(ListNode *head) { ListNode *p = head; set<ListNode *> s; while(p!=NULL) { if(s.count(p)) return true; else s.insert(p); p = p->next; } return false; } };
set无处不在,很多问题可以很方便的解决,就是用的空间不满足此题的要求。