链接
题面
思路 :
法1 :
用哈希表来存之前的遍历过的结点 ;
一遍遍历,在遍历的过程中,先判断是否当前结点在哈希表中出现过,如果出现过,直接返回true;
否则继续遍历,如果到遍历结束,证明没有环,直接返回false;
class Solution {
public:
bool hasCycle(ListNode *head) {
set<ListNode*> st ;
while(head){
if(st.count(head)) return true;
st.insert(head);
head = head -> next ;
}
return false;
}
};
法2
直接判断循环次数,因为也就最多也就1e4个结点,那么如果有环的话,那么一定会出现遍历次数大于10000的,在遍历的过程中,判断n是否大于10000,是的话,直接返回true;否则返回false ;
class Solution {
public:
bool hasCycle(ListNode *head) {
int n = 0 ;
while(head != nullptr){
n++ ;
head = head->next ;
if(n>10010){
return true;
}
}
return false;
}
};
法3
快慢双指针 -- > 算是本题的最优解了 ;
定义一个快慢双指针,快的每次跑两步,慢的每次跑一步;
如果存在环的话,那么快慢双指针一定都会进入环中,用相对速度思考,慢的不懂,快的每次前进一步,那么在环中,两个一定会相遇 ;
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head == nullptr || head->next == nullptr) return false;
ListNode* slow = head;
ListNode* fast = head->next;
while(slow != fast){
if(fast == nullptr || fast->next == nullptr){
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};