Hash Set
Intuition
The most straightforward way to detect a cycle is to keep track of every node we have visited. As we traverse the list, we check whether the current node has been seen before. If we encounter a previously visited node, a cycle exists. If we reach the end of the list (null), there is no cycle. This approach trades space for simplicity.
Algorithm
- Create an empty hash set to store visited node references.
- Start at `head` and traverse the list.
- For each node, check if it already exists in the set.
- If it does, return `true` (cycle detected).
- Otherwise, add the node to the set and move to the next node.
- If the traversal reaches null, return `false`.
O(n)SpaceO(n)Code (C++ · Java · Python · Go)
class Solution {
public:
bool hasCycle(ListNode *head) {
unordered_set<ListNode*> visited;
ListNode* curr = head;
while (curr != nullptr) {
if (visited.count(curr)) {
return true;
}
visited.insert(curr);
curr = curr->next;
}
return false;
}
};class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> visited = new HashSet<>();
ListNode curr = head;
while (curr != null) {
if (visited.contains(curr)) {
return true;
}
visited.add(curr);
curr = curr.next;
}
return false;
}
}def hasCycle(head: Optional[ListNode]) -> bool:
visited = set()
curr = head
while curr:
if curr in visited:
return True
visited.add(curr)
curr = curr.next
return Falsefunc hasCycle(head *ListNode) bool {
visited := map[*ListNode]bool{}
curr := head
for curr != nil {
if visited[curr] {
return true
}
visited[curr] = true
curr = curr.Next
}
return false
}