给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
方法一:哈希表
class Solution {
public:
bool hasCycle(ListNode *head) {
//如果给定的链表为空,直接返回空即可
if(head == nullptr) return false;
//创建一个哈希表用来存放链表中的数据
unordered_set<ListNode *> table;
ListNode* cur = head; //直接用head遍历链表也可以,因为后续不会再用到head,但是为了养成习惯,还是重新定一个节点吧。
//while循环结束的条件是cur为空,那么当cur指向空的时候也说明链表是不成环的(此时cur到达了链表的末尾),因为链表若是成环的话是不可能为空,只会进入链表成环的死循环
while(cur != nullptr){
//如果cur当前所指向的对象的地址在哈希表中存在的话,说明成环
if(table.count(cur) > 0){
return true;
}
//否则将其放入哈希表中并向下进行遍历
table.insert(cur);
cur = cur->next;
}
return false;
}
//时间复杂度:O(N),N为链表的长度
//空间复杂度:O(N),N为链表的长度,主要用于哈希表的开销
};
方法二:快慢指针
class Solution {
public:
bool hasCycle(ListNode *head) {
//判断给定的链表是否为空,如果为空,直接返回false
if(head == nullptr){
return false;
}
ListNode* fast = head;
ListNode* slow = head;
//先判断fast以及fast的next是否为空
//如果不判断的话假设当前fast为空,那么使用fast->next会出现错误
while(fast != nullptr && fast -> next != nullptr){
fast = fast -> next -> next;
slow = slow -> next;
//说明链表成环
if(fast == slow){
return true;
}
}
//说明链表不成环
return false;
}
//时间复杂度:O(N),其中N是链表中的节点数。
//空间复杂度:O(1)。我们只使用了两个指针的额外空间。
};