Copy List with Random Pointer
You're given the head of a linked list where each node has a value, a next pointer, and a random pointer that can point to any node in the list or to null. Return a deep copy: a new list of new nodes with the same values, where each copy's next and random pointers point to the matching copies. No pointer in the copy may point back into the original list.
Examples
head = [[5,null],[9,0],[2,1]] returns [[5,null],[9,0],[2,1]]
Each pair is [value, index of the random target]. The copy of 9 must point its random pointer at the copy of 5, and the copy of 2 at the copy of 9.
head = [[4,0]] returns [[4,0]]
The single node's random pointer points to itself, so the copy must point to itself too.
head = [] returns []
An empty list copies to an empty list.
Constraints
- 0 <= n <= 1000
- -10^4 <= Node.val <= 10^4
- Node.random is null or points to a node in the list.
Hints
Copying next pointers in one pass is easy. Why does the random pointer get in the way?
Keep a hash map from each original node to its copy, so any pointer in the original can be translated into the copy.
First pass: map every node to a new node with the same value. Second pass: set each copy's next and random to the copies of the original's next and random.
Drill This: Your Approach First
Approach
The difficulty is that a random pointer can point to a node whose copy does not exist yet. Solve it in two passes with a hash map from each original node to its copy. The first pass creates every copy with just its value. The second pass sets copy.next = map[node.next] and copy.random = map[node.random], with null mapping to null. O(n) time and O(n) space. Interleaving each copy right after its original removes the map and brings the space to O(1), at the cost of trickier pointer work.
Time
O(n)
Space
O(n)
Pitfall
Solutions
class Solution {
public Node copyRandomList(Node head) {
Map<Node, Node> copies = new HashMap<>();
for (Node cur = head; cur != null; cur = cur.next) {
copies.put(cur, new Node(cur.val));
}
for (Node cur = head; cur != null; cur = cur.next) {
Node copy = copies.get(cur);
copy.next = copies.get(cur.next);
copy.random = copies.get(cur.random);
}
return copies.get(head);
}
}from typing import Optional
class Solution:
def copyRandomList(self, head: Optional[Node]) -> Optional[Node]:
copies = {None: None}
cur = head
while cur:
copies[cur] = Node(cur.val)
cur = cur.next
cur = head
while cur:
copies[cur].next = copies[cur.next]
copies[cur].random = copies[cur.random]
cur = cur.next
return copies[head]