Copy a list with a random pointer

Deep-copy a list whose nodes carry a second, arbitrary 'random' pointer, without a dictionary mapping old nodes to new ones.

Time O(n)Space O(1)Code C#
Watch it animatedStep through it, with the running line highlighted. Free with an account.

The idea

Weave a copy of every node right after its original, so a copy always sits exactly one step past its original. That makes each copy's random pointer easy to set: follow the original's random pointer and step one further to land on its copy. A final pass then unweaves the two lists back apart.

Code

public static Node CopyRandomList(Node head) {
    if (head == null) return null;
    for (Node n = head; n != null; n = n.next.next) {
        var copy = new Node(n.val);
        copy.next = n.next; n.next = copy;
    }
    for (Node n = head; n != null; n = n.next.next) {
        n.next.random = n.random?.next;
    }
    Node dummy = new Node(0), tail = dummy;
    for (Node n = head; n != null; n = n.next) {
        tail.next = n.next; tail = tail.next;
        n.next = n.next.next;
    }
    return dummy.next;
}

Tips

In the .NET library

A Dictionary<Node,Node> solution is easier to write and just as valid at O(n) time — reach for the weave only when the O(1)-space constraint actually matters.