Input:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
Explanation:
Node 1's value is 1, both of its next and random pointer points to Node 2.
Node 2's value is 2, its next pointer points to null and its random pointer points to itself.
Note:
You must return the copy of the given head as a reference to the cloned list.
Solution & Analysis
HashMap 保存 old -> copy的映射,避免重复创建新Node。这样会用到O(n) space.
Approach 1: Recursion with O(N) Space
Complexity Analysis
Time Complexity: O(N) where N is the number of nodes in the linked list.
Space Complexity: O(N). If we look closely, we have the recursion stack and we also have the space complexity to keep track of nodes already cloned i.e. using the visited dictionary. But asymptotically, the complexity is O(N).
publicclassSolution {// HashMap which holds old nodes as keys and new nodes as its values.HashMap<Node,Node> visitedHash =newHashMap<Node,Node>();publicNodecopyRandomList(Node head) {if (head ==null) {returnnull; }// If we have already processed the current node, then we simply return the cloned version of// it.if (this.visitedHash.containsKey(head)) {returnthis.visitedHash.get(head); }// Create a new node with the value same as old node. (i.e. copy the node)Node node =newNode(head.val,null,null);// Save this value in the hash map. This is needed since there might be// loops during traversal due to randomness of random pointers and this would help us avoid// them.this.visitedHash.put(head, node);// Recursively copy the remaining linked list starting once from the next pointer and then from// the random pointer.// Thus we have two independent recursive calls.// Finally we update the next and random pointers for the new node created.node.next=this.copyRandomList(head.next);node.random=this.copyRandomList(head.random);return node; }}
*Approach 2: Iterative with O(N) Space
/*// Definition for a Node.class Node { public int val; public Node next; public Node random; public Node() {} public Node(int _val,Node _next,Node _random) { val = _val; next = _next; random = _random; }};*/classSolution {HashMap<Node,Node> map =newHashMap<>();privateNodegetCopy(Node node) {if (node ==null) {returnnull; }if (!map.containsKey(node)) {Node copy =newNode(node.val,null,null);map.put(node, copy);return copy; }returnmap.get(node); }publicNodecopyRandomList(Node head) {Node o = head;Node n =getCopy(o);while (o !=null) {n.random=getCopy(o.random);n.next=getCopy(o.next); o =o.next; n =n.next; }returngetCopy(head); }}
**Approach 3: Iterative with O(1) Space
比较巧妙的方法是,weave new node and old node, 利用位置关系,设定random指针,最后unweave。
A -> A' -> B -> B' -> C -> C'
Complexity Analysis
Time Complexity : O(n)
Space Complexity : O(1)
/*// Definition for a Node.class Node { public int val; public Node next; public Node random; public Node() {} public Node(int _val,Node _next,Node _random) { val = _val; next = _next; random = _random; }};*/publicclassSolution {// Visited dictionary to hold old node reference as "key" and new node reference as the "value"HashMap<Node,Node> visited =newHashMap<Node,Node>();publicNodegetClonedNode(Node node) {// If the node exists thenif (node !=null) {// Check if the node is in the visited dictionaryif (this.visited.containsKey(node)) {// If its in the visited dictionary then return the new node reference from the dictionaryreturnthis.visited.get(node); } else {// Otherwise create a new node, add to the dictionary and return itthis.visited.put(node,newNode(node.val,null,null));returnthis.visited.get(node); } }returnnull; }publicNodecopyRandomList(Node head) {if (head ==null) {returnnull; }Node oldNode = head;// Creating the new head node.Node newNode =newNode(oldNode.val);this.visited.put(oldNode, newNode);// Iterate on the linked list until all nodes are cloned.while (oldNode !=null) {// Get the clones of the nodes referenced by random and next pointers.newNode.random=this.getClonedNode(oldNode.random);newNode.next=this.getClonedNode(oldNode.next);// Move one step ahead in the linked list. oldNode =oldNode.next; newNode =newNode.next; }returnthis.visited.get(head); }}