LeetCode – Copy List with Random Pointer

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.

Java Solution 1

We can solve this problem by doing the following steps:

  1. copy every node, i.e., duplicate every node, and insert it to the list
  2. copy random pointers for all newly created nodes
  3. break the list to two
public RandomListNode copyRandomList(RandomListNode head) {
 
	if (head == null)
		return null;
 
	RandomListNode p = head;
 
	// copy every node and insert to list
	while (p != null) {
		RandomListNode copy = new RandomListNode(p.label);
		copy.next = p.next;
		p.next = copy;
		p = copy.next;
	}
 
	// copy random pointer for each new node
	p = head;
	while (p != null) {
		if (p.random != null)
			p.next.random = p.random.next;
		p = p.next.next;
	}
 
	// break list to two
	p = head;
	RandomListNode newHead = head.next;
	while (p != null) {
		RandomListNode temp = p.next;
		p.next = temp.next;
		if (temp.next != null)
			temp.next = temp.next.next;
		p = p.next;
	}
 
	return newHead;
}

The break list part above move pointer 2 steps each time, you can also move one at a time which is simpler, like the following:

while(p != null && p.next != null){
    RandomListNode temp = p.next;
    p.next = temp.next;
    p = temp;
}

Java Solution 2 - Using HashMap

From Xiaomeng's comment below, we can use a HashMap which makes it simpler.

public RandomListNode copyRandomList(RandomListNode head) {
	if (head == null)
		return null;
	HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
	RandomListNode newHead = new RandomListNode(head.label);
 
	RandomListNode p = head;
	RandomListNode q = newHead;
	map.put(head, newHead);
 
	p = p.next;
	while (p != null) {
		RandomListNode temp = new RandomListNode(p.label);
		map.put(p, temp);
		q.next = temp;
		q = temp;
		p = p.next;
	}
 
	p = head;
	q = newHead;
	while (p != null) {
		if (p.random != null)
			q.random = map.get(p.random);
		else
			q.random = null;
 
		p = p.next;
		q = q.next;
	}
 
	return newHead;
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Milan

    same as copying a list without random pointer, but before creating a new node check for presence in alreadyCreated map.

    public RandomListNode copyRandomList(RandomListNode head) {
    RandomListNode dummy = new RandomListNode(0);
    RandomListNode prev = dummy;
    //
    Map alreadyCreated = new HashMap();
    while(head != null){
    RandomListNode newNode = alreadyCreated.containsKey(head) ? alreadyCreated.get(head) : new RandomListNode(head.label);
    alreadyCreated.put(head,newNode);
    newNode.random = head.random == null || alreadyCreated.containsKey(head.random) ? alreadyCreated.get(head.random) : new RandomListNode(head.random.label);
    alreadyCreated.put(head.random,newNode.random);
    prev.next = newNode;
    prev = newNode;
    head = head.next;
    }
    return dummy.next;
    }

  • Ranjith Sompalli

    This is my solution

    public RandomListNode copyRandomList(RandomListNode head)

    {
    Map nodesMap = new HashMap();

    if(head == null)
    return null;

    RandomListNode first = head;
    while(head != null)
    {
    RandomListNode node = new RandomListNode(head.label);
    nodesMap.put(head,node);
    head = head.next;
    }

    for(RandomListNode originalNode : nodesMap.keySet())
    {
    nodesMap.get(originalNode).next = nodesMap.get(originalNode.next);
    nodesMap.get(originalNode).random = nodesMap.get(originalNode.random);
    }
    return nodesMap.get(first);
    }

  • Roderick Gao

    This is my solution: keep putting .random and next into HashMap, then we just need one iteration instead of two.

  • traceformula

    I also have the sames solutions. And I added another solution using recursion:
    ( url: http://traceformula.blogspot.com/2015/07/copy-list-with-random-pointers.html )

    public class Solution {

    public HashMap createdNode;

    public RandomListNode copyRandomList(RandomListNode head) {

    createdNode = new HashMap();

    return cc(head);

    }
    private RandomListNode cc(RandomListNode node) {

    if(node == null)

    {

    return null;

    }

    RandomListNode newNode = new RandomListNode(node.label);
    createdNode.put(node, newNode);

    newNode.next = cc(node.next);

    //now assign the random pointer

    RandomListNode newRandom = null;

    if(node.random != null)

    {

    newRandom = createdNode.get(node.random);

    }

    newNode.random = newRandom;

    return newNode;

    }

    }

  • nuurtila

    > RandomListNode newhead=head;
    This does not create a copy. Both p and q are references to the same list.

  • Monica Shankar

    can’t we simply do this

    p=head;
    RandomListNode newhead=head;
    q=newhead;

    while(p.random!=null)
    {
    q.label=p.label;
    q.random=p.random;
    q=q.random;
    p=p.random;
    }

    I really don’t see the point of having random and next as complementary fields for linkedlist. Correct me if I am wrong.

  • Alyssa Chen

    p.random is the node is the original list. Since newly added nodes are always the next to original nodes, so p.next.random = p.random.next;

  • Cracker
  • Parag Chaudhari

    This solution doesnot work if list has duplicate elements.

  • Wilson Ziyou Zheng

    I have a question about this line: p.next.random = p.random.next;,
    shouldn’t it be: p.next.random = p.random;

  • zhou2214

    good solutions

  • Kartrace

    That’s very nice solutions! The first might be very hard to think of if one were in the interview, it’s a little bit tricky, the second one is reasonable but with the cost of additional memory.

  • ryanlr

    Okay, I see.

  • I just put my code in <pre> <code>, and Disqus changed them, I don’t know why 🙁 Maybe the “>” confused Disquz.

    For first line, it should be HashMap < randomlistnode, randomlistnodepre > n2nMap = new HashMap < randomlistnode, randomlistnodepre >.

    And for the second line, it should be not existed.

  • ryanlr

    Good solution. Is this line legal?


    HashMap n2nMap = new HashMap();

  • xmpy

    What about using hash map to store the original node reference to new node reference mapping?
    My implementation is:
    (1) first foreach node in list, copy it, store the original node to new node mapping in hashmap

    (2)Still foreach node in original list, if its random attribute is not null, change the corresponding new node’s random attribute based on the hashmap.

    Here is my code:

    public RandomListNode copyRandomList(RandomListNode head) {
    if(head ==null)
    return null;
    HashMap n2nMap = new HashMap();
    RandomListNode newHead = new RandomListNode(head.label);
    RandomListNode p = head;
    RandomListNode q = newHead;
    n2nMap.put(head, newHead);
    p = p.next;
    while(p != null){
    RandomListNode temp = new RandomListNode(p.label);
    n2nMap.put(p,temp);
    q.next = temp;
    q = temp;
    p = p.next;
    }
    p = head;
    q = newHead;
    while(p!=null){
    if(p.random != null)
    q.random = n2nMap.get(p.random);
    else
    q.random = null;
    p = p.next;
    q = q.next;
    }
    return newHead;
    }