Solution 1
判断链表中有环,最直接的方案就是使用哈希表检查是否遍历过。
- 时间复杂度: O ( N ) O(N) O(N),其中 N N N为输入链表的长度,线性遍历一次
- 空间复杂度: O ( N ) O(N) O(N),其中 N N 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) {
if (head == nullptr) {
return false;
}
unordered_set<ListNode*> checked;
while (head != nullptr) {
if (checked.find(head) != checked.end()) {
return true;
}
checked.insert(head);
head = head->next;
}
return false;
}
};
Solution 2
【参考官方】参考官方题解环形链表 - 环形链表 - 力扣(LeetCode) (leetcode-cn.com) 中的Floyd 判圈算法。使用快慢指针在链表上遍历,如果存在环,那么总有一个时间快指针会从后面(正向遍历过程)追上满指针。
- 时间复杂度: O ( N ) O(N) O(N),其中 N N N为输入链表的长度,线性遍历,存在环的情况下至多遍历 2 N 2N 2N次
- 空间复杂度: O ( 1 ) O(1) 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 == nullptr || head->next == nullptr) {
return false;
}
auto slow = head;
auto fast = head->next;
// 利用快慢指针是否相遇确定是否存在环
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
Solution 3
Solution 1的Python实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None:
return False
checked = set()
while head is not None:
if head in checked:
return True
checked.add(head)
head = head.next
return False
Solution 4
Solution 2的Python实现