What if you could clone a complex web of secret friendships perfectly without losing a single connection?
Why Clone Linked List with Random Pointer in DSA Typescript?
Imagine you have a list of friends where each friend not only knows the next friend but also has a secret best friend anywhere in the list. Now, you want to make a perfect copy of this list including all these secret best friend links.
Trying to copy this list by hand means you must remember every friend and their secret best friend. It's easy to forget or mix up these secret links, making the copy wrong or incomplete. Doing this manually is slow and confusing.
Using the cloning method for a linked list with random pointers, you can cleverly create new friends right next to the originals, then fix all secret links in one go. This way, you get a perfect copy without losing track of any secret best friend.
let copyList = []; for (let i = 0; i < originalList.length; i++) { copyList.push(new Node(originalList[i].value)); // How to copy random pointers? Need extra loops and maps }
function cloneList(head) {
if (!head) return null;
// Step 1: Insert cloned nodes
let current = head;
while (current) {
let newNode = new Node(current.value);
newNode.next = current.next;
current.next = newNode;
current = newNode.next;
}
// Step 2: Assign random pointers
current = head;
while (current) {
if (current.random) {
current.next.random = current.random.next;
}
current = current.next.next;
}
// Step 3: Separate cloned list
current = head;
let clonedHead = head.next;
while (current) {
let clonedNode = current.next;
current.next = clonedNode.next;
clonedNode.next = clonedNode.next ? clonedNode.next.next : null;
current = current.next;
}
return clonedHead;
}This method lets you quickly and correctly duplicate complex linked lists with random connections, enabling safe data copying and manipulation.
Think of copying a social network where each user follows others randomly. Cloning this network exactly helps in testing new features without affecting real users.
Manual copying of random links is confusing and error-prone.
Cloning by interleaving nodes simplifies copying both next and random links.
This technique ensures a perfect duplicate of complex linked lists.
Practice
Solution
Step 1: Understand the structure of the linked list
The linked list has two pointers: next and random. The random pointer can point to any node or null.Step 2: Identify the cloning challenge
While copying nodes is straightforward, correctly assigning random pointers in the cloned list is tricky because they may point to nodes not yet cloned.Final Answer:
Maintaining the correct random pointer connections in the cloned list -> Option CQuick 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 for nullable pointers
Both next and random pointers can be null, so their types must allow null.Step 2: Verify constructor and property declarations
class Node { val: number; next: Node | null; random: Node | null; constructor(val?: number) { this.val = val ?? 0; this.next = null; this.random = null; } } correctly uses 'Node | null' and initializes properties properly with optional val.Final Answer:
Option A correctly declares nullable next and random pointers with proper constructor -> Option AQuick Check:
Nullable pointers + constructor = class Node { val: number; next: Node | null; random: Node | null; constructor(val?: number) { this.val = val ?? 0; this.next = null; this.random = null; } } [OK]
- Not allowing null for next or random
- Using interface without constructor
- Missing property initializations
class Node {
val: number;
next: Node | null;
random: Node | null;
constructor(val?: number) {
this.val = val ?? 0;
this.next = null;
this.random = null;
}
}
function cloneList(head: Node | null): Node | null {
if (!head) return null;
let curr = head;
while (curr) {
const copy = new Node(curr.val);
copy.next = curr.next;
curr.next = copy;
curr = copy.next;
}
curr = head;
while (curr) {
if (curr.random) curr.next!.random = curr.random.next;
curr = curr.next!.next;
}
curr = head;
const pseudoHead = new Node(0);
let copyCurr = pseudoHead;
while (curr) {
copyCurr.next = curr.next;
curr.next = curr.next!.next;
copyCurr = copyCurr.next;
curr = curr.next;
}
return pseudoHead.next;
}
// Original list: 1 -> 2 -> null
// Node 1 random points to Node 2
// Node 2 random points to Node 1
const node1 = new Node(1);
const node2 = new Node(2);
node1.next = node2;
node1.random = node2;
node2.random = node1;
const clonedHead = cloneList(node1);
console.log(clonedHead!.val);
console.log(clonedHead!.random!.val);
console.log(clonedHead!.next!.val);
console.log(clonedHead!.next!.random!.val);Solution
Step 1: Understand cloning steps
The code interleaves cloned nodes, assigns random pointers, then separates the cloned list.Step 2: Trace output values
clonedHead.val = 1; clonedHead.random.val = 2; clonedHead.next.val = 2; clonedHead.next.random.val = 1.Final Answer:
1 2 2 1 -> Option AQuick Check:
Cloned values and randoms match original pattern [OK]
- Not updating random pointers correctly
- Mixing original and cloned nodes in output
- Confusing next and random values
function cloneList(head: Node | null): Node | null {
if (!head) return null;
let curr = head;
while (curr) {
const copy = new Node(curr.val);
copy.next = curr.next;
curr.next = copy;
curr = curr.next;
}
curr = head;
while (curr) {
if (curr.random) curr.next!.random = curr.random.next;
curr = curr.next!.next;
}
curr = head;
const pseudoHead = new Node(0);
let copyCurr = pseudoHead;
while (curr) {
copyCurr.next = curr.next;
curr.next = curr.next!.next;
copyCurr = copyCurr.next;
curr = curr.next;
}
return pseudoHead.next;
}Solution
Step 1: Analyze the first while loop
Inside the loop, curr is updated as curr = curr.next, but curr.next is the cloned node, so curr never moves past cloned nodes, causing infinite loop.Step 2: Correct the pointer update
It should be curr = copy.next to move to the next original node.Final Answer:
In the first while loop, curr is updated incorrectly causing an infinite loop -> Option BQuick Check:
Incorrect curr update = infinite loop [OK]
- Updating curr to curr.next instead of curr.next.next
- Skipping random pointer assignment
- Not separating cloned list
Solution
Step 1: Understand random pointer complexities
Random pointers can be null or form cycles, so direct assignment during cloning is unsafe.Step 2: Use a hash map for safe cloning
Mapping original nodes to cloned nodes allows assigning random pointers correctly after all nodes are cloned, handling nulls and cycles safely.Final Answer:
Use a hash map to store original to cloned node mappings and assign random pointers after cloning all nodes -> Option DQuick Check:
Hash map handles nulls and cycles safely [OK]
- Ignoring null random pointers
- Trying to assign randoms in one pass without map
- Reversing list unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
