Copy List with Random Pointer medium
Problem Statement
A linked list of length n is given such that each node contains an integer val and a pointer to the next node in the list. The given head points to the beginning node of this list.
You must build a deep copy of the given linked list, including both the values in each node and pointers in the list structure. The deep copy should have the same values and structure as the original list, but be entirely separate from the original. Each node in the deep copy must contain a copy of the val
of its corresponding node in the original list, as well as the next
and random
pointers pointing to the corresponding nodes in the deep copy.
Note:
- The linked list can have cycles.
- You must return the head node of the newly created deep copy list.
Example 1
Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] Output: [[7,null],[13,0],[11,4],[10,2],[1,0]] Explanation:
The input is a linked list containing 5 nodes. The integer values are [7, 13, 11, 10, 1]. The random
pointers point to the nodes with the integer values as indicated. The output is a deep copy of this list, where the new nodes have the same values and random
pointer relationships.
Example 2
Input: head = [[1,1],[2,1]] Output: [[1,1],[2,1]] Explanation: The input list has a cycle. The deep copy must also have the same cycle structure.
Steps
-
Create a mapping: We'll use a
unordered_map
to store a mapping between nodes in the original list and their corresponding nodes in the copied list. This allows us to easily find the copied node when we need to set therandom
pointer. -
Iterate and copy: Iterate through the original list. For each node:
- Create a new node with the same
val
. - Store the mapping between the original node and the new node in the
unordered_map
. - Set the
next
pointer of the newly created node.
- Create a new node with the same
-
Set random pointers: Iterate through the original list again. For each node, use the mapping to find the corresponding copied node and set its
random
pointer to the copied version of therandom
pointer from the original node. -
Return the head of the copied list: Return the first node of the copied list.
Explanation
The key to solving this problem efficiently is using a hash map (unordered_map in C++) to avoid repeated searches and to maintain the correspondence between nodes in the original and copied lists. The iterative approach ensures we process each node exactly twice, resulting in linear time complexity. The space complexity is also linear due to the hash map.
Code (C++)
#include <iostream>
#include <unordered_map>
struct Node {
int val;
Node *next;
Node *random;
Node(int x) : val(x), next(nullptr), random(nullptr) {}
};
Node* copyRandomList(Node* head) {
if (head == nullptr) return nullptr;
unordered_map<Node*, Node*> visited; // Map original node to copied node
Node* oldNode = head;
Node* newNode = new Node(oldNode->val); // Create the first node copy
visited[oldNode] = newNode; // Store the mapping
while (oldNode != nullptr) {
//copy next pointer
if(oldNode->next != nullptr){
if(visited.find(oldNode->next) == visited.end()){
visited[oldNode->next] = new Node(oldNode->next->val);
}
newNode->next = visited[oldNode->next];
}
//copy random pointer
if(oldNode->random != nullptr){
if(visited.find(oldNode->random) == visited.end()){
visited[oldNode->random] = new Node(oldNode->random->val);
}
newNode->random = visited[oldNode->random];
}
oldNode = oldNode->next;
newNode = newNode->next;
}
return visited[head];
}
int main() {
// Example usage (you can adapt this to test other inputs)
Node* head = new Node(7);
head->next = new Node(13);
head->next->next = new Node(11);
head->next->next->next = new Node(10);
head->next->next->next->next = new Node(1);
head->random = head->next->next->next->next;
head->next->random = head;
head->next->next->random = head->next->next->next->next;
head->next->next->next->random = head->next->next;
head->next->next->next->next->random = head;
Node* copiedHead = copyRandomList(head);
// Print the copied list (You would need a function to properly print the list's structure)
// ... (Add code here to print the copied list)
return 0;
}
Complexity
- Time Complexity: O(N), where N is the number of nodes in the list. We iterate through the list twice.
- Space Complexity: O(N). The
unordered_map
uses O(N) space in the worst case to store the mapping between original and copied nodes.