Understanding the Problem
The core challenge of this problem is to create a deep copy of a linked list where each node has an additional random pointer. The deep copy should be a completely new list with no shared nodes with the original list. This problem is significant in scenarios where data structures need to be duplicated without affecting the original structure, such as in undo operations, cloning complex objects, etc.
Approach
To solve this problem, we can use a three-step approach:
- Interweaving the original list with copied nodes: For each node in the original list, create a new node and insert it right after the original node. This helps in easily setting the random pointers in the next step.
- Setting the random pointers: For each new node, set its random pointer to the copied node corresponding to the original node's random pointer.
- Restoring the original list and extracting the copied list: Separate the interwoven list into the original list and the copied list.
Algorithm
Let's break down the algorithm step-by-step:
- Traverse the original list and create new nodes, inserting each new node right after its corresponding original node.
- Traverse the list again to set the random pointers for the new nodes.
- Separate the interwoven list into the original list and the copied list.
Code Implementation
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
public class Solution {
public Node copyRandomList(Node head) {
if (head == null) {
return null;
}
// Step 1: Create new nodes and interweave them with the original nodes
Node current = head;
while (current != null) {
Node newNode = new Node(current.val);
newNode.next = current.next;
current.next = newNode;
current = newNode.next;
}
// Step 2: Set the random pointers for the new nodes
current = head;
while (current != null) {
if (current.random != null) {
current.next.random = current.random.next;
}
current = current.next.next;
}
// Step 3: Separate the interwoven list into original and copied lists
current = head;
Node newHead = head.next;
Node copy = newHead;
while (current != null) {
current.next = current.next.next;
if (copy.next != null) {
copy.next = copy.next.next;
}
current = current.next;
copy = copy.next;
}
return newHead;
}
}
Complexity Analysis
The time complexity of this algorithm is O(n) because we traverse the list a constant number of times. The space complexity is O(1) extra space because we are not using any additional data structures that grow with the input size.
Edge Cases
Consider the following edge cases:
- An empty list (head is null).
- A list where all random pointers are null.
- A list where random pointers form a cycle.
Our algorithm handles these cases effectively by ensuring that the deep copy is created correctly regardless of the random pointer configuration.
Testing
To test the solution comprehensively, consider the following test cases:
- Simple lists with no random pointers.
- Lists with random pointers pointing to various nodes.
- Edge cases like empty lists and single-node lists.
Use a testing framework like JUnit to automate the testing process.
Thinking and Problem-Solving Tips
When approaching such problems, consider breaking down the problem into smaller, manageable steps. Visualize the problem with diagrams to understand the relationships between nodes. Practice similar problems to improve your problem-solving skills.
Conclusion
In this blog post, we discussed how to create a deep copy of a linked list with random pointers in Java. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for developing strong problem-solving skills in computer science.

