思路1:使用set存储
判断有无环,可以使用set集合,判断是否有节点已经在集合中,如果在就有环,如果遍历完,没有重复节点,就代表无环
时间复杂度O(n)
空间复杂度O(n) 因为使用了一个set集合
struct ListNode{
int val;
ListNode * next;
ListNode(int x) : val(x) , next(NULL){}
};
class Solution {
public:
bool hasCycle(ListNode *head) {
//定义一个set集合
set<ListNode*> s;
while(head) {
//查找set集合是否有当前元素,有代表有环,没有就添加进集合
if (s.find(head) != s.end()) {
return true;
} else {
s.insert(head);
}
head = head->next;
}
//查找完没有相同代表无环
return false;
}
};
思路2:快慢指针思想
如果有环,就像操场一样,跑的快的会追上跑得慢的。
定义两个指针 一个快一个慢 , 如果快的 == 慢的 就代表有环。
时间复杂度O(n)
空间复杂度O(1)
struct ListNode{
int val;
ListNode * next;
ListNode(int x) : val(x) , next(NULL){}
};
class Solution {
public:
bool hasCycle(ListNode *head) {
//定义快指针
ListNode* fast = head;
//定义慢指针
ListNode* slow = head;
//快指针一定是先跑完的,如果没环,快指针最先到达NULL
while(fast) {
//一开始都先跑一步
fast = fast->next;
slow = slow->next;
//要判断一下 快指针是否还能再跑,因为如果链表为1,那么快指针就已经为空
// 如果为空 代表链表无环 直接返回
if(fast)
fast = fast->next;
else
return false;
//判断两个是否相遇 相遇就代表有环
if(fast == slow)
return true;
}
return false;
}
};