C++ 0141.cpp
class Solution {
public:
bool hasCycle(ListNode *head) {
// don't wanna use the famous algorithm ...
unordered_set<ListNode*> seen;
while (head)
{
if (seen.count(head) > 0)
return true;
seen.insert(head);
head = head->next;
}
return false;
}
};
Difficulty
and has an acceptance rate of about 55% (9+ million submissions).
Typical patterns to solve this problem:
- Hash Table
- Linked List
- Two Pointers
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The presented function determines whether a singly-linked list contains a cycle. It follows a straightforward approach: it traverses the list while recording each visited node in a hash-based container. If a node is encountered that already exists in the container, a cycle is reported; otherwise the traversal reaches the end of the list and the function returns false. The implementation relies on the standard library’s unordered_set to achieve constant-time membership checks.
Core Logic
Initialization of the tracking container
At the start of the routine an empty hash set is created to store pointers to the nodes that have been seen so far.
unordered_set<ListNode*> seen;
The choice of a hash set provides rapid insertion and lookup, which is essential for keeping the traversal efficient even for long lists.
Iterative traversal
The function enters a loop that continues as long as the current pointer is not null. The loop condition directly reflects the natural end of a non-cyclic list.
while (head)
{
// body omitted for clarity
}
Cycle detection
Inside the loop the first operation checks whether the current node pointer already resides in the seen set. The count method returns a non-zero value when the element is present, triggering an immediate return of true.
if (seen.count(head) > 0)
return true;
This early-exit strategy prevents unnecessary processing once a cycle is identified.
Recording the node and advancing
If the node has not been seen, it is inserted into the set, and the pointer advances to the next element in the list.
seen.insert(head);
head = head->next;
The insertion step guarantees that any future encounter with the same node will be caught by the detection check.
Completion without a cycle
When the loop terminates because head becomes null, the function concludes that no cycle exists and returns false.
return false;
Edge Cases Handled
The algorithm gracefully manages several boundary conditions without additional code.
When the input list is empty (head is null), the loop body is never executed and the function returns false, correctly indicating the absence of a cycle.
A list consisting of a single node that does not point to itself also bypasses the detection condition, proceeds to the end, and yields false.
If a node’s next pointer references itself, the node is inserted into the set on the first iteration, and the subsequent iteration finds the same pointer already present, causing an immediate return of true.
These scenarios demonstrate that the implementation covers the full spectrum of minimal and degenerate list configurations.
Performance Optimizations Observed
The use of unordered_set provides average-case constant-time operations for both insertion and membership testing, which keeps the overall execution time proportional to the number of distinct nodes visited.
The early return upon detecting a repeated node eliminates further traversal, saving work in the presence of a cycle that appears early in the list.
By storing raw pointers rather than copying node contents, the memory footprint of each entry in the set remains minimal, and the insertion operation avoids costly deep copies.
The loop advances the pointer directly after insertion, ensuring that each node is processed exactly once in the non-cyclic case, which avoids redundant checks.
Overall, the design balances simplicity with effective use of standard library facilities to achieve a responsive solution for cycle detection.
ELI5 - Simplified Explanation
Imagine you are walking along a path made of stepping stones, and each stone has a little arrow pointing to the next one. This code is like holding a magic scrapbook as you walk. Every time you step on a stone, you take a quick snapshot of it and glue it into your book.
As you move from one stone to the next, you pause for a second to check your scrapbook. You look through all the pages to see if you have already stepped on the stone you are currently standing on. If you find a picture of your current stone in the book, it means you have accidentally walked in a circle and ended up back where you started. If you find that page, you know for sure that the path is a loop. If you reach a stone that does not have an arrow pointing to anything else, you know the path ends and there is no loop to worry about.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | ||||||||||
| www | AlgoMonster | C++ | Python | Java | TS | ||||||
| WalkCCC | C++ | Python | Java | ||||||||
| leetcode.ca | C++ | Python | Java | C# | JS | Go | TS | ||||
| LeetcodeHelp | C++ | Python | Java | ||||||||
| MemoryLimitExceeded | C++ | Python | |||||||||
| Progiez | C++ | Python | Java | ||||||||
| github | begeekmyfriend | C | |||||||||
| BigEggStudy | C# | ||||||||||
| black-shadows | C++ | ||||||||||
| bujosa | Rust | ||||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| chenyanzhe | C++ | ||||||||||
| Dijkstra-Edu | Java | ||||||||||
| DimitrisJim | C | ||||||||||
| everthis | JS | ||||||||||
| fartem | Ruby | ||||||||||
| FelixFan1122 | C# | ||||||||||
| fengvyi | C++ | ||||||||||
| fpdjsns | C++ | ||||||||||
| gaosq0604 | Python | ||||||||||
| Garvit244 | Python | ||||||||||
| gouthampradhan | Java | ||||||||||
| halfrost | Go | ||||||||||
| haoel | C++ | ||||||||||
| JoshCrozier | JS | ||||||||||
| keineahnung2345 | C++ | ||||||||||
| Krazune | C | ||||||||||
| lennylxx | C | ||||||||||
| linouk23 | C++ | ||||||||||
| lkwq007 | Python | ||||||||||
| luangong | C++ | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| pruthvikp | Python | ||||||||||
| qiyuangong | Python | ||||||||||
| shreymehul | C# | ||||||||||
| sonugiri1043 | C++ | ||||||||||
| suxrobGM | C# | ||||||||||
| trung-hn | Python | ||||||||||
| varunu28 | Java | ||||||||||
| vli02 | C | ||||||||||
| vthwang | Java | ||||||||||
| wisdompeak | C++ | ||||||||||
| XiaotaoGuo | C++ | ||||||||||
| YuriSpiridonov | Python | ||||||||||
| zfang399 | C++ | ||||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||||
| WalkCCC | C++, Python, Java | ||||||||||
| leetcode.ca | C++, C#, Go, Java, JavaScript, Python, TypeScript | ||||||||||
| LeetcodeHelp | C++, Java, Python | ||||||||||
| MemoryLimitExceeded | Python, C++ | ||||||||||
| Progiez | C++, Java, Python | ||||||||||
| begeekmyfriend | C | ||||||||||
| BigEggStudy | C# | ||||||||||
| black-shadows | C++, C++ | ||||||||||
| bujosa | Rust | ||||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| chenyanzhe | C++ | ||||||||||
| Dijkstra-Edu | Java | ||||||||||
| DimitrisJim | C | ||||||||||
| everthis | JavaScript | ||||||||||
| fartem | Ruby | ||||||||||
| FelixFan1122 | C# | ||||||||||
| fengvyi | C++ | ||||||||||
| fpdjsns | C++ | ||||||||||
| gaosq0604 | Python | ||||||||||
| Garvit244 | Python | ||||||||||
| gouthampradhan | Java | ||||||||||
| halfrost | Go | ||||||||||
| haoel | C++ | ||||||||||
| JoshCrozier | JavaScript | ||||||||||
| keineahnung2345 | C++ | ||||||||||
| Krazune | C | ||||||||||
| lennylxx | C | ||||||||||
| linouk23 | C++ | ||||||||||
| lkwq007 | Python | ||||||||||
| luangong | C++ | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| pruthvikp | Python | ||||||||||
| qiyuangong | Python | ||||||||||
| shreymehul | C# | ||||||||||
| sonugiri1043 | C++ | ||||||||||
| suxrobGM | C# | ||||||||||
| trung-hn | Python | ||||||||||
| varunu28 | Java | ||||||||||
| vli02 | C | ||||||||||
| vthwang | Java | ||||||||||
| wisdompeak | C++ | ||||||||||
| XiaotaoGuo | C++ | ||||||||||
| YuriSpiridonov | Python | ||||||||||
| zfang399 | C++ |
Videos
Similar Problems
- problem 142: Linked List Cycle II
- problem 202: Happy Number
Solved On The Same Day
- problem 1: Two Sum
- problem 9: Palindrome Number
- problem 14: Longest Common Prefix
- problem 20: Valid Parentheses
- problem 26: Remove Duplicates from Sorted Array
- problem 27: Remove Element
- problem 83: Remove Duplicates from Sorted List
- problem 88: Merge Sorted Array
- problem 94: Binary Tree Inorder Traversal
- problem 100: Same Tree
- problem 104: Maximum Depth of Binary Tree
- problem 121: Best Time to Buy and Sell Stock
- problem 136: Single Number
- problem 169: Majority Element
- problem 190: Reverse Bits
- problem 226: Invert Binary Tree
- problem 234: Palindrome Linked List
- problem 1114: Print in Order
- problem 3: Longest Substring Without Repeating Characters
- problem 7: Reverse Integer
- problem 8: String to Integer (atoi)
- problem 11: Container With Most Water
- problem 12: Integer to Roman
- problem 15: 3Sum
- problem 17: Letter Combinations of a Phone Number
- problem 22: Generate Parentheses
- problem 31: Next Permutation
- problem 36: Valid Sudoku
- problem 39: Combination Sum
- problem 40: Combination Sum II
- problem 45: Jump Game II
- problem 46: Permutations
- problem 47: Permutations II
- problem 48: Rotate Image
- problem 49: Group Anagrams
- problem 55: Jump Game
- problem 59: Spiral Matrix II
- problem 75: Sort Colors
- problem 77: Combinations
- problem 91: Decode Ways
- problem 95: Unique Binary Search Trees II
- problem 96: Unique Binary Search Trees
- problem 134: Gas Station
- problem 164: Maximum Gap
- problem 189: Rotate Array
- problem 215: Kth Largest Element in an Array
- problem 238: Product of Array Except Self
- problem 287: Find the Duplicate Number
- problem 322: Coin Change
- problem 347: Top K Frequent Elements
- problem 377: Combination Sum IV
- problem 438: Find All Anagrams in a String
- problem 474: Ones and Zeroes
- problem 518: Coin Change II
- problem 526: Beautiful Arrangement
- problem 763: Partition Labels
- problem 983: Minimum Cost For Tickets
- problem 994: Rotting Oranges
- problem 1027: Longest Arithmetic Subsequence
- problem 2140: Solving Questions With Brainpower
- problem 2466: Count Ways To Build Good Strings
- problem 4: Median of Two Sorted Arrays
- problem 41: First Missing Positive
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality