Question:
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
Solution1:
public class Solution {
HashMap<RandomListNode, RandomListNode> visited = new HashMap<RandomListNode, RandomListNode>();
// method for the mapping of old and new nodes
// the parameter is the old node, and the return value is the corresponding cloned new node
private RandomListNode clonedNode(RandomListNode node) {
if (node != null) {
// if the cloned node is already created
if (visited.containsKey(node)) {
return visited.get(node);
}
// if the cloned node has not been created yet
else {
// create the node and put it into the map
visited.put(node, new RandomListNode(node.label));
return visited.get(node);
}
}
return null;
}
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null) {
return null;
}
// if head != null, create a new head
RandomListNode newHead = new RandomListNode(head.label);
RandomListNode oldCur = head, newCur = newHead;
while (oldCur != null) {
newCur.next = clonedNode(oldCur.next);
newCur.random = clonedNode(oldCur.random);
newCur = newCur.next;
oldCur = oldCur.next;
}
}
return newHead;
}
Note:
- To create a cloned list, is actually creating a mapping from an old list to a new list. (To create a map, we can use a hashmap directly, instead of using the index or the sequence of the nodes in the list.)
- To avoid the duplication of new nodes, before creating new nodes, we check if it already exists.
- Time Complexity : O(N)O(N) because we make one pass over the original linked list.
- Space Complexity : O(N)O(N) as we have a dictionary containing mapping from old list nodes to new list nodes. Since there are NN nodes, we have O(N)O(N) space complexity. Space Complexity : O(N)O(N) as we have a dictionary containing mapping from old list nodes to new list nodes. Since there are NN nodes, we have O(N)O(N) space complexity.
Solution2:
tweak the original linked list and keep every cloned node next to its original node.
public class Solution {
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null) {
return null;
}
//tweak the original linked list and keep every cloned node next to its original node.
RandomListNode cur = head;
while (cur != null) {
RandomListNode newNode = new RandomListNode(cur.label);
newNode.next = cur.next;
cur.next = newNode;
cur = newNode.next;
}
// find random node list for the new nodes
cur = head;
while (cur != null) {
cur.next.random = (cur.random == null) ? null : cur.random.next;
cur = cur.next.next;
}
// seperate the tweaked nodes
RandomListNode oldCur = head, newCur = head.next, newHead = head.next;
while (oldCur != null) {
oldCur.next = oldCur.next.next;
newCur.next = (newCur.next == null) ? null : newCur.next.next;
oldCur = oldCur.next;
newCur = newCur.next;
}
return newHead;
}
}
Notes:
- Don’t modify the input parameter
- Time Complexity : O(N)
- Space Complexity : O(1)
Solution3: Recursion
public class Solution {
HashMap<RandomListNode, RandomListNode> visited = new HashMap<RandomListNode, RandomListNode>();
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null) {
return null;
}
if (visited.containsKey(head)) {
return visited.get(head);
}
RandomListNode node = new RandomListNode(head.label);
visited.add(head,node);
head.next = copyRandomList(head.next);
head.random = copyRandomList(head.random);
return node;
}
}