Clone Linked List with Random Pointer in DSA C - Time & Space Complexity
We want to understand how long it takes to copy a linked list where each node has a random pointer.
How does the time grow as the list gets bigger?
Analyze the time complexity of the following code snippet.
// Clone linked list with random pointer
Node* cloneList(Node* head) {
if (!head) return NULL;
Node* curr = head;
// Step 1: Insert cloned nodes
while (curr) {
Node* newNode = malloc(sizeof(Node));
newNode->val = curr->val;
newNode->next = curr->next;
curr->next = newNode;
curr = newNode->next;
}
// Step 2: Set random pointers
curr = head;
while (curr) {
if (curr->random) curr->next->random = curr->random->next;
curr = curr->next->next;
}
// Step 3: Separate lists
curr = head;
Node* cloneHead = head->next;
Node* cloneCurr = cloneHead;
while (curr) {
curr->next = curr->next->next;
if (cloneCurr->next) cloneCurr->next = cloneCurr->next->next;
curr = curr->next;
cloneCurr = cloneCurr->next;
}
return cloneHead;
}
This code creates a copy of each node, sets the random pointers for the copies, and then separates the original and cloned lists.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Three separate while loops each traversing the entire list once.
- How many times: Each loop runs once over all n nodes, so about 3n steps total.
As the list size grows, the number of steps grows roughly in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 30 steps |
| 100 | About 300 steps |
| 1000 | About 3000 steps |
Pattern observation: The operations grow linearly with the number of nodes.
Time Complexity: O(n)
This means the time to clone the list grows in a straight line as the list gets longer.
[X] Wrong: "Because there are nested steps, the time must be quadratic O(n²)."
[OK] Correct: Each loop runs separately over the list, not inside each other, so the total work adds up linearly, not multiplies.
Understanding this linear time cloning method shows you can handle complex pointer structures efficiently, a valuable 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 linked list structure
A linked list with random pointers has two pointers per node: next and random. The random pointer can point to any node or null.Step 2: Identify cloning challenge
While copying nodes is straightforward, correctly assigning random pointers in the cloned list is tricky because random pointers may point to nodes not yet cloned.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
- Assuming random pointers are always null
- Copying only next pointers
Solution
Step 1: Check correct malloc usage
In C, malloc requires sizeof(Node) to allocate memory. Casting to (Node*) is good practice.Step 2: Verify initialization
New node's data is copied, next and random pointers are set to NULL initially to avoid dangling pointers.Final Answer:
Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = oldNode->data; newNode->next = NULL; newNode->random = NULL; -> Option AQuick Check:
Correct malloc and initialization = Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = oldNode->data; newNode->next = NULL; newNode->random = NULL; [OK]
- Missing sizeof in malloc
- Not casting malloc result
- Copying next and random pointers directly
Node1(data=1) -> Node2(data=2) -> NULL
Node1.random = Node2
Node2.random = Node2
What will be the random pointer of the cloned Node1 after cloning?
Solution
Step 1: Understand original random pointers
Original Node1's random points to original Node2.Step 2: Cloning preserves structure
Cloned Node1's random should point to cloned Node2, not original nodes, to maintain independence.Final Answer:
Points to cloned Node2 -> Option BQuick Check:
Random pointer in clone = cloned target node [OK]
- Random pointer points to original node
- Random pointer set to NULL by mistake
- Confusing next and random pointers
while (curr != NULL) {
Node* copy = (Node*)malloc(sizeof(Node));
copy->data = curr->data;
copy->next = curr->next;
curr->next = copy;
curr = curr->next;
}What is the main error causing an infinite loop?
Solution
Step 1: Analyze pointer updates in loop
After inserting copy node after curr, curr->next points to copy. Moving curr = curr->next moves to copy again.Step 2: Identify infinite loop cause
Loop never advances past copy node because curr is updated to copy, not original next node. It should be curr = curr->next->next.Final Answer:
Not updating curr to curr->next->next after insertion -> Option CQuick Check:
Advance curr by two nodes after insertion [OK]
- Advancing curr by one node causes infinite loop
- Forgetting to link copy nodes properly
- Incorrect malloc size
Solution
Step 1: Understand space and time constraints
O(n) time and O(1) space means no extra data structures like hash maps.Step 2: Use interleaving method
Insert cloned nodes between original nodes, assign random pointers using original nodes, then detach cloned list. This avoids extra space.Final Answer:
Create copy nodes interleaved with original nodes, set random pointers using original nodes, then separate lists -> Option DQuick Check:
Interleaving nodes = O(1) space cloning [OK]
- Using hash map increases space complexity
- Searching original list for random pointers is O(n^2)
- Reversing list does not help cloning random pointers
Ready to prove it?
Pass the test and this pattern moves unknown
