Clone Linked List Random Pointers — Undo Stack Corruption
Shallow-copying random pointers caused cross-contamination in undo stacks.
- Core challenge: a copied pointer still points into the original structure. You must remap every pointer to the corresponding clone.
- HashMap approach (O(n) space): two passes — first create all clones, then wire next/random using the map.
- Weaving approach (O(1) space): interleave clones between originals, set randoms via A.random.next, then un-weave.
- Forward reference problem: when processing node A, A.random's clone may not exist yet. HashMap or weaving solves this.
- Production risk: shallow copy (pointing random at original nodes) causes silent data corruption when the original is mutated.
- This is a graph-traversal problem disguised as a linked-list problem — the random pointer breaks linearity.
Imagine you have a classroom seating chart where every student has a 'best friend' who can sit anywhere in the room — not just next to them. Now your teacher asks you to photocopy the entire class with all those friendships intact. You can't just copy names in order — you have to make sure every copied student's best-friend pointer aims at the right copy, not the original. That's exactly the problem: duplicating a linked list where each node has a mystery arrow that can point to any node, or to nothing at all.
Deep-copying a linked list with random pointers is a pointer-remapping problem. Each node has two outgoing references: next (sequential) and random (arbitrary). A naive copy creates new nodes but leaves random pointers pointing at the original structure — a shallow copy that corrupts when the original is mutated.
The random pointer breaks the list's linearity. When processing node A, its random target (node 7) may not have been cloned yet. Two strategies solve this: a HashMap that pre-creates all clones before wiring pointers, or an interweaving trick that places each clone adjacent to its original so the clone is always reachable via original.next.
This problem appears in serialization of graph-like structures, deep-copying editor undo/redo trees, and duplicating compiler adjacency representations. In production, a shallow copy bug manifests as cross-contamination between independent data structures — one structure's mutation silently affects another.
What is Clone a Linked List with Random Pointers? — Plain English
Each node in this linked list has a next pointer (to the following node) and a random pointer (to any node in the list, or None). Cloning it naively requires two passes: one to create new nodes, and a second to set random pointers. A hash map from original_node -> cloned_node makes both passes easy and is the standard O(n) time, O(n) space approach.
The key challenge: when you create a new node and want to set its random pointer, the target of the random pointer may not have been created yet. The hash map solves this by building all new nodes first, then linking them.
- Photocopying a seating chart copies names in order — but the 'best friend' arrows still point at the original students.
- You need a name-to-copy mapping so every arrow can be redirected to the photocopy.
- Without the mapping, the photocopy is a shallow copy — it shares state with the original.
- The HashMap is that name-to-copy mapping. The weaving trick achieves the same without explicit storage.
How Clone a Linked List with Random Pointers Works — Step by Step) time, O(n) space): 1. Pass 1 — create all new nodes: For each node in the original list: map[original] = Node(original.val). 2. Pass 2 — set pointers: For each node in the original list: map[node].next = map[node.next] (or None if node.next is None). map[node].random = map[node.random] (or None). 3. Return map[head]. O(1) space approach (weaving): 1. Insert each cloned node right after its original: A -> A' -> B -> B' -> ... 2. Set random pointers: A'.random = A.random.next (the clone of A's random). 3. Un-weave: restore original list and extract cloned list.
Hash map, making it unsafe for concurrent access.
- After interleaving, every clone is exactly one hop from its original: original.next = clone.
- So clone.random = original.random.next — the clone of the random target is always its next node.
- No HashMap needed — the interleaved structure IS the mapping.
- The un-weave step restores both lists by separating odd-positioned (original) and even-positioned (clone) nodes.
Worked Example — Tracing the Algorithm
List: 1 -> 2 -> 3 -> None. Random pointers: 1.random=3, 2.random=1, 3.random=2.
Pass 1 — create map: map[1] = Node(1), map[2] = Node(2), map[3] = Node(3).
Pass 2 — set pointers: map[1].next = map[2]. map[1].random = map[3]. map[2].next = map[3]. map[2].random = map[1]. map[3].next = None. map[3].random = map[2].
Cloned list: 1'->2'->3'. 1'.random=3', 2'.random=1', 3'.random=2'. Fully independent deep copy.
- Print System.identityHashCode(original) and System.identityHashCode(clone.random).
- If they match, clone.random points at the original — shallow copy bug.
- If clone.random's hash matches map.get(original.random)'s hash, the copy is correct.
- This works because identity hash is based on memory address, not value.
Implementation
The implementation uses two passes. In the first pass, iterate the original list and create a new node for each original node, storing the mapping in a hash map. In the second pass, use the hash map to wire up the next and random pointers on each new node. This runs in O(n) time and O(n) space. The alternative O(1) space approach interleaves cloned nodes between original nodes, sets random pointers, then splits the two lists apart in a third pass.
- Weaving: original list is modified during cloning. Unsafe for concurrent access.
- HashMap: original list is never modified. Safe for concurrent read access.
- If the original list is a field in a shared object, weaving introduces a data race.
- The O(1) space saving of weaving is not worth a concurrency bug in production.
The Undo Stack That Cross-Contaminated Editor Sessions
- A deep copy must remap ALL pointers — not just next. Random/arbitrary pointers are the common oversight.
- Shallow copy of random pointers creates cross-contamination between a silent corruption bug — no exception, no crash, just wrong behavior.
- Post-clone invariant checks (no original nodes reachable from clone) catch shallow-copy bugs in debug builds.
- The forward-reference problem (random target not yet cloned) requires either pre-creation (HashMap) or structural interleaving (weaving).
Key takeaways
Interview Questions on This Topic
Frequently Asked Questions
That's Linked List. Mark it forged?
3 min read · try the examples if you haven't