Copy linked list with random pointer

Posted by achild on Mon, 13 Dec 2021 13:26:48 +0100

LeetCode 138: copy linked list with random pointer

https://leetcode-cn.com/probl...

1, Title Description

Give you a linked list with a length of n. each node contains an additional random pointer random, which can point to any node or empty node in the linked list.

Construct a deep copy of this linked list. The deep copy should consist of exactly n new nodes, in which the value of each new node is set to the value of its corresponding original node. The next pointer and random pointer of the new node should also point to the new node in the replication linked list, and these pointers in the original linked list and the replication linked list can represent the same linked list state. The pointer in the copy linked list should not point to the node in the original linked list.

For example, if there are two nodes X and Y in the original linked list, where x.random -- > y. Then, the corresponding two nodes X and Y in the copy linked list also have x.random -- > y.

Returns the header node of the copy linked list.

A linked list composed of n nodes is used to represent the linked list in input / output. Each node is represented by a [val, random_index]:

Val: one represents node Integer of val.

random_index: the node index pointed to by the random pointer (ranging from 0 to n-1); if it does not point to any node, it is null.

Your code only accepts the head node of the original linked list as the incoming parameter.

Node definition:

class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

2, Example

Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]

3, Train of thought

Additional space complexity O(1)

1. After each node in the original linked list, copy a new node and connect it to the old node

Namely:

Before copying: 1 - > 2 - > 3,

After copying: 1 - > 1 \ ` - > 2 - > 2 \ ` - > 3 - > 3\`

2. Copy the relationship between the original node and the random pointer in the new node

3. Separating old and new nodes

Additional space complexity O(N)

1. Use Map to store new and old nodes. Key: old node, Value: new node

2. Construct a new node corresponding to the old node

3. Adjust the next pointer of the new node and the random pointer of the new node

4, Source code

Additional space complexity O(1)

/**
 * @author Java And algorithm learning: Monday
 */
public Node copyRandomList(Node head) {
    if (head == null) {
        return null;
    }

    // 1. Insert the new node behind the old node
    //Before adjustment: 1 - > 2 - > 3 - > null; after adjustment: 1 - > 1 ` - > 2 - > 2 ` - > 3 - > 3 ` - > null
    Node current = head;
    Node next = null;
    while (current != null) {
        //Mark the next node of the current node in the original linked list
        next = current.next;
        //Insert a new node after the current node of the original linked list
        current.next = new Node(current.val);
        //Adjust the next node of the newly inserted node
        current.next.next = next;
        //Move current node backward
        current = next;
    }

    // 2. Adjust the random pointer of the newly inserted node
    Node copy = null;
    current = head;
    while (current != null) {
        //New node
        copy = current.next;
        //Mark the next node of the current node in the original linked list
        next = current.next.next;
        //Adjust the new node's random node
        copy.random = current.random != null ? current.random.next : null;
        //Move current node backward
        current = next;
    }

    // 3. Separating old and new nodes
    current = head;
    //Record the header node of the new linked list
    Node res = head.next;
    while (current != null) {
        //New node
        copy = current.next;
        //Mark the next node of the current node in the original linked list
        next = current.next.next;
        //The next node of the current node points to the next node of the current node in the original linked list (that is, adjust the reference of the old node back)
        current.next = next;
        //The next node of the new node points to the next node of the current node in the original linked list (that is, extract the reference of the new node)
        copy.next = next != null ? next.next : null;
        //Move current node backward
        current = next;
    }

    //Returns the header node of the new linked list
    return res;
}

Additional space complexity O(N)

/**
 * @author Java And algorithm learning: Monday
 */
public Node copyRandomListByMap(Node head) {
    // Key: old node, Value: new node
    HashMap<Node, Node> map = new HashMap<>();
    Node current = head;
    while (current != null) {
        //Construct a new node corresponding to the old node
        map.put(current, new Node(current.val));
        current = current.next;
    }

    current = head;
    while (current != null) {
        //Adjust the next pointer of the new node
        map.get(current).next = map.get(current.next);
        //Adjust the random pointer of the new node
        map.get(current).random = map.get(current.random);
        current = current.next;
    }

    return map.get(head);
}

5, Test results

Additional space complexity O(1)

Additional space complexity O(N)

It can be seen from the official test results of LeetCode that there is no difference in execution time, and the difference in memory consumption (i.e. additional space complexity) is obvious. One beat 99.94% of users and the other beat only 48.64% of users.

Topics: Java Algorithm leetcode