package main import "fmt" type Node struct { Val int Next *Node Random *Node } func cloneList(head *Node) *Node { if head == nil { return nil } curr := head // Step 1: Insert cloned nodes for curr != nil { newNode := &Node{Val: curr.Val} newNode.Next = curr.Next curr.Next = newNode curr = newNode.Next } // Step 2: Assign random pointers curr = head for curr != nil { if curr.Random != nil { curr.Next.Random = curr.Random.Next } curr = curr.Next.Next } // Step 3: Separate lists curr = head cloneHead := head.Next cloneCurr := cloneHead for curr != nil { curr.Next = curr.Next.Next if cloneCurr.Next != nil { cloneCurr.Next = cloneCurr.Next.Next } curr = curr.Next cloneCurr = cloneCurr.Next } return cloneHead } func printList(head *Node) { curr := head for curr != nil { randomVal := "null" if curr.Random != nil { randomVal = fmt.Sprint(curr.Random.Val) } fmt.Printf("%d(random:%s) -> ", curr.Val, randomVal) curr = curr.Next } fmt.Println("null") } func main() { // Create list: 1->2->3->null n1 := &Node{Val: 1} n2 := &Node{Val: 2} n3 := &Node{Val: 3} n1.Next = n2 n2.Next = n3 // Random pointers n1.Random = n3 n2.Random = n1 n3.Random = n2 clone := cloneList(n1) printList(clone) }
The cloned list preserves the original random pointer connections. Node 1's random points to Node 3, Node 2's random points to Node 1, and Node 3's random points to Node 2.
By placing cloned nodes right after original nodes, the algorithm can assign the clone's random pointer by accessing original.Random.Next, which is the clone of the original's random node.
func cloneList(head *Node) *Node {
if head == nil {
return nil
}
curr := head
for curr != nil {
newNode := &Node{Val: curr.Val}
newNode.Next = curr.Next
curr.Next = newNode
curr = curr.Next
}
return head.Next
}The line curr = curr.Next moves curr to the newly inserted clone node, causing the loop to never reach the original next node, resulting in an infinite loop.
package main import "fmt" type Node struct { Val int Next *Node Random *Node } func separateLists(head *Node) *Node { curr := head cloneHead := head.Next cloneCurr := cloneHead for curr != nil { curr.Next = curr.Next.Next if cloneCurr.Next != nil { cloneCurr.Next = cloneCurr.Next.Next } curr = curr.Next cloneCurr = cloneCurr.Next } return cloneHead } func printList(head *Node) { curr := head for curr != nil { fmt.Printf("%d -> ", curr.Val) curr = curr.Next } fmt.Println("null") } func main() { // Original list: 1->2->3->null n1 := &Node{Val: 1} n2 := &Node{Val: 2} n3 := &Node{Val: 3} n1.Next = n2 n2.Next = n3 // Interleaved cloned nodes: 1->1'->2->2'->3->3'->null n1.Next = &Node{Val: 1, Next: n2} n2.Next = &Node{Val: 2, Next: n3} n3.Next = &Node{Val: 3, Next: nil} clone := separateLists(n1) printList(n1) }
The separation loop restores the original list by skipping cloned nodes, so the original list remains 1 -> 2 -> 3 -> null.
The interleaving method clones nodes in O(n) time and uses no extra space besides the cloned nodes themselves, achieving O(1) auxiliary space.
