You are given the head of a linked list of length n. Each node has a val, a next pointer, and a random pointer that may point to any node or null. Create a deep copy: exactly n new nodes, no pointers into the original list.
0 ≤ n ≤ 100-100 ≤ Node.val ≤ 100random is null or points to some node in the list.Use a hash map to memoize every node we've cloned. On each call, if the node is already in the map return its copy; otherwise create the copy, store it, then recurse for next and look up random.
head is None → return None.head in map return cached copy (handles shared random targets).next, then wire random.Time: O(n) | Space: O(n) map + O(n) stack
Pass 1: traverse and create a copy for every node, storing original → copy in a map. Pass 2: traverse again and wire copy.next and copy.random by looking up the map. All copies exist before any pointer is wired.
oldToCopy = { None: None }.oldToCopy[head].Time: O(n) | Space: O(n)
Python's collections.defaultdict auto-creates a new Node(0) when a key is first accessed. In a single pass, set val, next, and random simultaneously — accessing oldToCopy[cur.next] creates the stub for cur.next on the fly if it hasn't been visited yet. Gray nodes in the visualization are those pre-created stubs.
oldToCopy[None] = None.cur: set val, next, random in one iteration.Time: O(n) | Space: O(n)
next O(1) extra spaceWeave copy nodes into the original list using next pointers: A → A' → B → B' → …. Each copy sits immediately after its original, so A.random.next gives the copy of A's random target — no hash map needed.
A, create A' and insert it as A.next.A'.random = A.random.next (if random ≠ null).A.next and link A'.next = A'.next.next.Time: O(n) | Space: O(1) extra (O(n) output)
random O(1) extra spaceInstead of the next pointer, temporarily use random to store copies: set A.random = A' (copy) and A'.next = A's original random target. The purple downward arrows in the visualization show this temp random-as-map link.
A: create A', set A'.next = A.random (save), set A.random = A' (map).A'.random = A'.next.random if A'.next else None.A.random = A'.next; link A'.next = A.next.random if A.next.Time: O(n) | Space: O(1) extra (O(n) output)
Without a map, multiple random pointers targeting the same node each trigger a fresh Node(...), producing duplicates. Always check the map first.
# Wrong — creates a new copy every time: copy.random = Node(original.random.val) # Correct — reuse from map: copy.random = oldToCopy[original.random]
The map must include a None → None entry (Python) or a null check; otherwise accessing oldToCopy[null] throws a KeyError / NullPointerException.
In the interleaving approach, the unweave pass must correctly restore original.next to point to the next original node. Failing corrupts the original list and may break the copy list's own chain.
Discussion
…