Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
Given head, the head of a linked list, determine if the linked list has a cycle in it.
There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to. Note that pos is not passed as a parameter.
Return true if there is a cycle in the linked list. Otherwise, return false.
Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: true Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).
Example 2:
Input: head = [1,2], pos = 0 Output: true Explanation: There is a cycle in the linked list, where the tail connects to the 0th node.
Example 3:
Input: head = [1], pos = -1 Output: false Explanation: There is no cycle in the linked list.
Constraints:
[0, 104].-105 <= Node.val <= 105pos is -1 or a valid index in the linked-list.Follow up: Can you solve it using O(1) (i.e. constant) memory?
Problem summary: Given head, the head of a linked list, determine if the linked list has a cycle in it. There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to. Note that pos is not passed as a parameter. Return true if there is a cycle in the linked list. Otherwise, return false.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Linked List · Two Pointers
[3,2,0,-4] 1
[1,2] 0
[1] -1
linked-list-cycle-ii)happy-number)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #141: Linked List Cycle
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> s = new HashSet<>();
for (; head != null; head = head.next) {
if (!s.add(head)) {
return true;
}
}
return false;
}
}
// Accepted solution for LeetCode #141: Linked List Cycle
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func hasCycle(head *ListNode) bool {
s := map[*ListNode]bool{}
for ; head != nil; head = head.Next {
if s[head] {
return true
}
s[head] = true
}
return false
}
# Accepted solution for LeetCode #141: Linked List Cycle
# 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:
s = set()
while head:
if head in s:
return True
s.add(head)
head = head.next
return False
// Accepted solution for LeetCode #141: Linked List Cycle
use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;
// Definition for singly-linked list.
// #[derive(PartialEq, Eq)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Rc<RefCell<ListNode>>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
impl Solution {
pub fn has_cycle(head: Option<Rc<RefCell<ListNode>>>) -> bool {
let mut seen: HashSet<*const RefCell<ListNode>> = HashSet::new();
let mut cur = head;
while let Some(node) = cur {
let ptr = Rc::as_ptr(&node);
if !seen.insert(ptr) {
return true;
}
cur = node.borrow().next.clone();
}
false
}
}
// Accepted solution for LeetCode #141: Linked List Cycle
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function hasCycle(head: ListNode | null): boolean {
const s: Set<ListNode> = new Set();
for (; head; head = head.next) {
if (s.has(head)) {
return true;
}
s.add(head);
}
return false;
}
Use this to step through a reusable interview workflow for this problem.
Copy all n nodes into an array (O(n) time and space), then use array indexing for random access. Operations like reversal or middle-finding become trivial with indices, but the O(n) extra space defeats the purpose of using a linked list.
Most linked list operations traverse the list once (O(n)) and re-wire pointers in-place (O(1) extra space). The brute force often copies nodes to an array to enable random access, costing O(n) space. In-place pointer manipulation eliminates that.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Pointer updates overwrite references before they are saved.
Usually fails on: List becomes disconnected mid-operation.
Fix: Store next pointers first and use a dummy head for safer joins.
Wrong move: Advancing both pointers shrinks the search space too aggressively and skips candidates.
Usually fails on: A valid pair can be skipped when only one side should move.
Fix: Move exactly one pointer per decision branch based on invariant.