Copy List with Random Pointer
Deep-copy a linked list with next and random pointers — hash map O(n) space vs interleaving nodes O(1) extra space.
intermediate3 min read
- dsa
- linked-list
- interview
- Meta
- Amazon
- Microsoft
The problem
Each node has val, next, and random (points to any node or null). Return a deep copy of the list.
7 → 13 → 11 → 10 → 1
randoms can point anywhere (including self / null)
next alone is easy; random may point forward or backward, so you can’t clone in one naïve pass without remembering original→copy.
Approach A — Hash map (clear interview default)
- Walk list; create clone nodes; map original → clone.
- Second pass:
clone.next = map.get(orig.next), same forrandom.
class Node {
val: number;
next: Node | null;
random: Node | null;
constructor(val?: number, next?: Node | null, random?: Node | null) {
this.val = val ?? 0;
this.next = next ?? null;
this.random = random ?? null;
}
}
function copyRandomList(head: Node | null): Node | null {
if (!head) return null;
const map = new Map<Node, Node>();
let cur: Node | null = head;
while (cur) {
map.set(cur, new Node(cur.val));
cur = cur.next;
}
cur = head;
while (cur) {
const clone = map.get(cur)!;
clone.next = cur.next ? map.get(cur.next)! : null;
clone.random = cur.random ? map.get(cur.random)! : null;
cur = cur.next;
}
return map.get(head)!;
}
| Time | O(n) |
| Space | O(n) |
Approach B — Interleave (O(1) extra space)
- After each original
A, insert cloneA':A → A' → B → B' … - Set
A'.random = A.random.next(the clone of random). - Unweave into original and copy lists.
function copyRandomListO1(head: Node | null): Node | null {
if (!head) return null;
// 1. interleave clones
let cur: Node | null = head;
while (cur) {
const copy = new Node(cur.val, cur.next, null);
cur.next = copy;
cur = copy.next;
}
// 2. random pointers
cur = head;
while (cur) {
if (cur.random) cur.next!.random = cur.random.next;
cur = cur.next!.next;
}
// 3. unweave
const dummy = new Node(0);
let copyTail = dummy;
cur = head;
while (cur) {
const copy = cur.next!;
cur.next = copy.next;
copyTail.next = copy;
copyTail = copy;
cur = cur.next;
}
return dummy.next;
}
| Time | O(n) |
| Space | O(1) extra (not counting output) |
Interviewers love hearing both; implement map unless they demand O(1) extra.
Edge cases
- Empty list
- Single node, random to self
- random all null
- random forms cycles of references (still fine — not a graph walk of next)
Common mistakes
- Setting random before all clones exist (map approach: two passes)
- Forgetting to restore original list in interleave method
- Shallow copy of node objects
Related to frontend?
Rarely product code — but the identity map while cloning a cyclic structure matches cloning fiber-like graphs or editor document models with cross-refs.
Interview delivery
- Deep copy next + random.
- Map first.
- Optional interleave for O(1) space.
- Null safety on random.
- Complexities.