题目
给定一个链表,判断链表中是否有环。
思路
用hashset存储已遍历的结点
- 时间复杂度O(N)
- 空间复杂度O(N)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
//用hashset存储已遍历过的结点
unordered_set<ListNode*> unset;
ListNode *p = head;
while( p!=NULL ){
if( unset.find(p)!=unset.end() ){
return true;
}else{
unset.insert(p);
p = p->next;
}
}
return false;
}
};
快慢指针
慢指针每次向前走一步,快指针每次向前走两步。
- 如果没有环,快指针一定比慢指针更快到达尾部结点NULL,并停留在那
- 如果存在环,快指针会比慢指针更快进入环,且在环内循环转圈,直到慢指针也加入到环内,且经过一段时间,快慢指针一定会相遇。
- 时间复杂度O(N)
- 空间复杂度O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL || head->next==NULL){
return false;
}
//快慢指针
ListNode *slow = head;
ListNode *fast = head->next;
while( slow!=fast ){//两个指针一旦相遇,那就有环
//只要指向尾部NULL,就说明没环
if(slow==NULL || fast==NULL){
return false;
}
//否则就继续遍历
slow = slow->next;
if(fast->next==NULL){ //注意快指针这里需要判断一下
return false;
}else{
fast = fast->next->next;
}
}
return true;
}
};