Clone linked list with next and random pointer

Spread the love

Each node in a linked list of size N contains two links: a random pointer to any random node in the list and a next pointer to the next node. Making a copy of this linked list is the work at hand.

Table of Content

How to use a random pointer and next to clone a linked list:

To store the new nodes that correspond to their original nodes, create a hash table with the value mp.
For each node in the original linked list, say curr,
mp[curr] = new Node() creates a new node that corresponds to curr and pushes it into a hash table.
To update the next and random pointer of every new node, iterate through the original linked list once more: mp[curr]->next = mp[curr->next] and mp[curr]->random = mp[curr->random].
Return the cloned linked list’s head, mp[head].
The application of the aforementioned strategy is seen below:

C++14

// C++ code to Clone a linked list with next and random
// pointer using Hashing 

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node* random;
  
    Node(int x) {
        data = x;
        next = random = NULL;
    }
};

// Function to clone the linked list
Node* cloneLinkedList(Node* head) {
  
    // Map to store new nodes corresponding to
      // their original nodes
    unordered_map<Node*, Node*> mp;
    Node *curr = head;
  
    // Traverse original linked list to store new 
      // nodes corresponding to original linked list
    while (curr != NULL) {
        mp[curr] = new Node(curr->data);
        curr = curr->next;
    }
    
      curr = head;
      
    // Loop to update the next and random pointers 
      // of new nodes 
    while (curr != NULL) {
        
          // Update the next pointer of new node
          mp[curr]->next = mp[curr->next];
      
          // Update the random pointer of new node
          mp[curr]->random = mp[curr->random];
      
          curr = curr->next;
    }
  
    // Return the head of the clone
    return mp[head];
}

// Function to print the linked list
void printList(Node* head) {
    while (head != NULL) {
        cout << head->data << "(";
          if(head->random)
              cout << head->random->data << ")";
          else 
              cout << "null" << ")";
        
          if(head->next != NULL)
              cout << " -> ";
        head = head->next;
    }
    cout << endl;
}

int main() {
  
    // Creating a linked list with random pointer
    Node* head = new Node(1);
    head->next = new Node(2);
    head->next->next = new Node(3);
    head->next->next->next = new Node(4);
    head->next->next->next->next = new Node(5);
    head->random = head->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->next;
  
    // Print the original list
    cout << "Original linked list:\n";
    printList(head);
  
    // Function call
    Node* clonedList = cloneLinkedList(head);
  
    cout << "Cloned linked list:\n";
    printList(clonedList);
  
    return 0;
}

Java

// Java code to Clone a linked list with next and random
// pointer using Hashing

import java.util.HashMap;
import java.util.Map;

// Define the Node class
class Node {
    int data;
    Node next;
    Node random;
  
    Node(int x) {
        data = x;
        next = null;
        random = null;
    }
}

class GfG {

    // Function to clone the linked list
    static Node cloneLinkedList(Node head) {
  
        // Hash Map to store new nodes corresponding  
          // to their original nodes
        Map<Node, Node> mp = new HashMap<>();
        Node curr = head;
  
        // Traverse original linked list to store new nodes 
          // corresponding to original linked list
        while (curr != null) {
            mp.put(curr, new Node(curr.data));
            curr = curr.next;
        }
    
        curr = head;
    
        // Loop to update the next and random pointers
          // of new nodes 
        while (curr != null) {
        
            // Update the next pointer of new node
            Node newNode = mp.get(curr);
            newNode.next = mp.get(curr.next);
      
            // Update the random pointer of new node
            newNode.random = mp.get(curr.random);
      
            curr = curr.next;
        }
  
        // Return the head of the clone
        return mp.get(head);
    }

    // Function to print the linked list
    static void printList(Node head) {
        while (head != null) {
            System.out.print(head.data + "(");
            if (head.random != null)
                System.out.print(head.random.data + ")");
            else 
                System.out.print("null" + ")");
        
            if (head.next != null)
                System.out.print(" -> ");
            head = head.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
  
        // Creating a linked list with random pointer
        Node head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
        head.random = head.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.next;
  
        // Print the original list
        System.out.println("Original linked list:");
        printList(head);
  
        // Function call
        Node clonedList = cloneLinkedList(head);
  
        System.out.println("Cloned linked list:");
        printList(clonedList);
    }
}

Python

# Python code to Clone a linked list with next and random
# pointer using Hashing

class Node:
    def __init__(self, x):
        self.data = x
        self.next = None
        self.random = None

# Function to clone the linked list
def clone_linked_list(head):
      
    # Dictionary to store new nodes corresponding 
    # to their original nodes
    mp = {}
    curr = head
    
    # Traverse original linked list to store new nodes 
    # corresponding to original linked list
    while curr is not None:
        mp[curr] = Node(curr.data)
        curr = curr.next
    
    curr = head
    
    # Loop to update the next and random pointers
    # of new nodes
    while curr is not None:
        new_node = mp[curr]
        
        # Update the next pointer of new node
        new_node.next = mp.get(curr.next)
        
        # Update the random pointer of new node
        new_node.random = mp.get(curr.random)
        curr = curr.next
    
    # Return the head of the clone
    return mp.get(head)

def print_list(head):
    curr = head
    while curr is not None:
        print(f'{curr.data}(', end='')
        if curr.random:
            print(f'{curr.random.data})', end='')
        else:
            print('null)', end='')
        
        if curr.next is not None:
            print(' -> ', end='')
        curr = curr.next
    print()

if __name__ == "__main__":
    
    # Creating a linked list with random pointer
    head = Node(1)
    head.next = Node(2)
    head.next.next = Node(3)
    head.next.next.next = Node(4)
    head.next.next.next.next = Node(5)
    
    head.random = head.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.next
    
    # Print the original list
    print("Original linked list:")
    print_list(head)
    
    # Function call
    cloned_list = clone_linked_list(head)
    
    print("Cloned linked list:")
    print_list(cloned_list)

JS

// JavaScript code to Clone a linked list with next 
// and random pointer using Hashing 


class Node {
    constructor(data) {
        this.data = data;
        this.next = null;
        this.random = null;
    }
}

// Function to clone the linked list
function cloneLinkedList(head) {
    
    // Map to store new nodes corresponding to 
    // their original nodes
    const mp = new Map();
    let curr = head;

    // Traverse original linked list to store new nodes
    // corresponding to original linked list
    while (curr !== null) {
        mp.set(curr, new Node(curr.data));
        curr = curr.next;
    }
    
    curr = head;
    
    // Loop to update the next and random pointers
    // of new nodes
    while (curr !== null) {
        const newNode = mp.get(curr);
        newNode.next = mp.get(curr.next) || null;
        newNode.random = mp.get(curr.random) || null;
        curr = curr.next;
    }
  
    // Return the head of the clone
    return mp.get(head) || null;
}

// Function to print the linked list
function printList(head) {
    let result = "";
    while (head !== null) {
        result += head.data + "(";
        result += head.random ? head.random.data : "null";
        result += ")";

        if (head.next !== null) {
            result += " -> ";
        }
        head = head.next;
    }
    console.log(result);
}


// Creating a linked list with random pointer
const head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(5);

head.random = head.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.next;

// Print the original list
console.log("Original linked list:");
printList(head);

// Function call
const clonedList = cloneLinkedList(head);

console.log("Cloned linked list:");
printList(clonedList);

Output

Original linked list:
1(3) -> 2(1) -> 3(5) -> 4(3) -> 5(2)
Cloned linked list:
1(3) -> 2(1) -> 3(5) -> 4(3) -> 5(2)

Time Complexity: O(2n), as we are traversing the linked list twice. 
Auxiliary Space: O(2n), extra O(n) space as we are using a hash table to store the new nodes.