Title Description
 Given a linked list of length 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 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 by the random pointer (range from 0 to n1); null if it does not point to any node.
 The code only accepts the head node of the original linked list as the incoming parameter.
example input : head = [[7,null],[13,0],[11,4],[10,2],[1,0]] output : [[7,null],[13,0],[11,4],[10,2],[1,0]] input : head = [[3,null],[3,0],[3,null]] output : [[3,null],[3,0],[3,null]]
Problem solving ideas
Idea 1 hash table

Traverse the original linked list, ignore the random pointer, deeply copy the original nodes one by one and form a new linked list. In this process, use the hash table map to record each pair of < old nodes, new nodes >.

Traverse the original linked list and the new linked list to judge whether the random pointer of the current original node oldnode is empty. If not, let newnode Random points to the oldnode in the map Random as the value of the key, that is, newnode random = map. get(oldNode.random)

Time complexity: O(n)

Space complexity: O(n)
Idea 2 in situ algorithm

Don't consider the random pointer for the time being. First deep copy and insert a node with the same value after each node of the original linked list

That is, assuming that the original linked list is 1  > 2  > 3, after traversing and inserting, the list is updated to 1  > 1  > 2  > 2  > 3  > 3

Traverse the linked list again, and copy the random pointer relationship of the original list node to the new linked list of intervals according to the front and back relationship in the current linked list

That is, assuming that the current node is node, when node When random is not empty, node next. random = node.random. next

Then, the node advances two positions to bypass the newly copied linked list node

Finally, split the new and old linked list and return to the new linked list

Time complexity: O(n)

Space complexity: O(1)
Idea 3 backtracking + hash table

Using backtracking, the copy operations of each node are independent of each other.

For the current node, copy it first, and record each pair of < old node, new node >, with a hash table.

Recursively create the node of the current node Next and the node pointed to by the random pointer of the current node random.

Since a node may be pointed to by multiple other nodes, you may try to copy a node multiple times during recursion.

To prevent duplicate copying, you need to first check whether the current node has been copied, that is, whether it has existed in the hash table as a value. If it has been copied, you can directly take it out of the hash table and return it.

Time complexity: O(n)

Space complexity: O(n)
Code (Java)
Train of thought 1 code
public class Solution1 { public Node copyRandomList(Node head) { if (head == null) { return null; } Map<Node, Node> map = new HashMap<>(); Node newHead = new Node(1); Node scan = head; Node append = newHead; while (scan != null) { Node newNode = new Node(scan.val); map.put(scan, newNode); append.next = newNode; scan = scan.next; append = append.next; } scan = head; append = newHead.next; while (scan != null) { if (scan.random != null) { append.random = map.get(scan.random); } scan = scan.next; append = append.next; } return newHead.next; } }
Train of thought 2 code
public class Solution2 { public Node copyRandomList(Node head) { if (head == null) { return null; } Node scan = head; while (scan != null) { Node newNode = new Node(scan.val); newNode.next = scan.next; scan.next = newNode; scan = newNode.next; } scan = head; while (scan != null) { if (scan.random != null) { scan.next.random = scan.random.next; } scan = scan.next.next; } Node newList = head.next; Node oldList = head; Node res = head.next; while (newList != null && oldList != null) { oldList.next = newList.next; oldList = oldList.next; if (oldList != null) { newList.next = oldList.next; newList = newList.next; } } return res; } }
public class Solution3 { private Map<Node, Node> map = new HashMap<>(); public Node copyRandomList(Node head) { if (head == null) { return null; } if (!map.containsKey(head)) { Node headNew = new Node(head.val); map.put(head, headNew); headNew.next = copyRandomList(head.next); headNew.random = copyRandomList(head.random); } return map.get(head); } }