Clone Linked List with Random Pointer in DSA C++ - Time & Space Complexity
We want to understand how the time needed to clone a linked list with random pointers changes as the list grows.
Specifically, how the number of steps grows when the list has more nodes.
Analyze the time complexity of the following code snippet.
struct Node {
int val;
Node* next;
Node* random;
Node(int x) : val(x), next(nullptr), random(nullptr) {}
};
Node* cloneList(Node* head) {
if (!head) return nullptr;
// Step 1: Insert cloned nodes
Node* curr = head;
while (curr) {
Node* copy = new Node(curr->val);
copy->next = curr->next;
curr->next = copy;
curr = copy->next;
}
// Step 2: Assign random pointers
curr = head;
while (curr) {
if (curr->random) {
curr->next->random = curr->random->next;
}
curr = curr->next->next;
}
// Step 3: Separate the lists
curr = head;
Node* copyHead = head->next;
Node* copyCurr = copyHead;
while (curr) {
curr->next = curr->next->next;
if (copyCurr->next) {
copyCurr->next = copyCurr->next->next;
}
curr = curr->next;
copyCurr = copyCurr->next;
}
return copyHead;
}
This code clones a linked list where each node has a next pointer and a random pointer to any node or null.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Three separate while loops each traversing the entire list.
- How many times: Each loop runs once over all n nodes, so about 3n steps total.
As the list size grows, the total steps grow roughly in direct proportion to the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 30 steps (3 loops x 10 nodes) |
| 100 | About 300 steps |
| 1000 | About 3000 steps |
Pattern observation: The steps increase linearly as the list size increases.
Time Complexity: O(n)
This means the time to clone the list grows in a straight line with the number of nodes.
[X] Wrong: "Because there are nested steps, the time is O(n²)."
[OK] Correct: Each loop runs separately over the list, not inside each other, so the total steps add up linearly, not multiply.
Understanding this linear time cloning method shows you can handle complex pointer structures efficiently, a useful skill in many coding challenges.
"What if we used a hash map to store original-to-clone node mappings instead of inserting cloned nodes inline? How would the time complexity change?"
Practice
Solution
Step 1: Understand the structure of the linked list
The linked list has two pointers: next and random. The next pointer points to the next node, and the random pointer can point to any node or null.Step 2: Identify the cloning challenge
While copying nodes is straightforward, correctly assigning the random pointers in the cloned list is tricky because they can point anywhere in the original list.Final Answer:
Maintaining the correct random pointer connections in the cloned list -> Option AQuick Check:
Random pointer cloning = main challenge [OK]
- Ignoring random pointers during cloning
- Only copying next pointers
- Assuming random pointers follow next pointers
Solution
Step 1: Understand pointer usage in C++ structs
To link nodes, pointers to Node type are needed for next and random pointers.Step 2: Check each option's correctness
struct Node { int data; Node* next; Node* random; }; uses Node* for next and random, which is correct. Those using Node without pointer are invalid. struct Node { int data; Node* next; int random; }; uses int for random, which is incorrect.Final Answer:
struct Node { int data; Node* next; Node* random; }; -> Option AQuick Check:
Use pointers for next and random [OK]
- Using Node instead of Node* for pointers
- Using int type for random pointer
- Missing semicolon after struct
struct Node {
int data;
Node* next;
Node* random;
Node(int x) : data(x), next(nullptr), random(nullptr) {}
};
// Original list: 1 -> 2 -> 3 -> null
// random pointers: 1.random = 3, 2.random = 1, 3.random = 2
// After cloning, print cloned list data:
Node* cloneHead = cloneLinkedList(head); // Assume correct cloning function
Node* temp = cloneHead;
while(temp) {
std::cout << temp->data << " ";
temp = temp->next;
}Solution
Step 1: Understand the cloning process
The cloneLinkedList function creates a new list with the same data and next pointer order as the original list.Step 2: Trace the output loop
The loop prints data of cloned nodes in order: first node data 1, then 2, then 3.Final Answer:
1 2 3 -> Option CQuick Check:
Cloned list data order = original order [OK]
- Confusing random pointer order with next pointer order
- Printing random pointer data instead of next
- Assuming reversed list after cloning
Node* cloneLinkedList(Node* head) {
if (!head) return nullptr;
Node* curr = head;
while (curr) {
Node* newNode = new Node(curr->data);
newNode->next = curr->next;
curr->next = newNode;
curr = newNode->next;
}
curr = head;
while (curr) {
if (curr->random) {
curr->next->random = curr->random->next;
}
curr = curr->next->next;
}
Node* original = head, *copy = head->next, *temp = copy;
while (original && copy) {
original->next = original->next->next;
copy->next = copy->next ? copy->next->next : nullptr;
original = original->next;
copy = copy->next;
}
return temp;
}Solution
Step 1: Analyze node insertion loop
The first loop inserts cloned nodes after each original node correctly.Step 2: Analyze random pointer assignment and list separation
The second loop assigns random pointers correctly. The final loop restores original and cloned lists properly.Final Answer:
No error; the code correctly clones the list -> Option BQuick Check:
Code follows standard cloning steps [OK]
- Misreading pointer assignments
- Assuming random pointer assignment is wrong without checking
- Confusing original and cloned list restoration
Solution
Step 1: Understand space constraints
Using extra data structures like hash maps or vectors uses extra space.Step 2: Identify O(1) space cloning method
Interleaving cloned nodes with original nodes allows assigning random pointers without extra space, then separating lists restores original and cloned lists.Final Answer:
Create cloned nodes interleaved with original nodes, assign random pointers, then separate lists -> Option DQuick Check:
Interleaving nodes = O(1) space cloning [OK]
- Using hash maps when O(1) space is required
- Trying to clone by reversing list
- Using extra arrays or vectors unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
