# 138. Copy List with Random Pointer

{% embed url="<https://leetcode.com/problems/copy-list-with-random-pointer/>" %}

Iterate the linked list twice:&#x20;

1. first round copying the node value, and mapping the original node to new generated node.&#x20;
2. second round assigning the random pointer in new linked list by hash map.

```python
"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    def copyRandomList(self, head):
        # 建立一个值为 0 的新 node，它的 next 和 random 都是 None
        copy = Node(0)
        # 将 curNode 指针放在 copy 当前位置 i.e 0
        curNode = copy
        # 用来临时存储随即指针的 hash map
        randomPointerMap = {}

        # 遍历原始链表，拷贝每个 node 的值，记录随机指针到 hash map
        while head is not None:
            # 根据原始链表生成下一个新节点（有值，但next和random都是None）
            newNode = Node(head.val)
            # 把新节点接到当前节点后面
            curNode.next = newNode
            # 把原始链表上的节点map到新链表上的对应节点
            randomPointerMap[head] = newNode
            # 从原始链表上拷贝随机指针
            newNode.random = head.random
            # 移动指针到下一个node
            head = head.next
            curNode = curNode.next

        # 遍历新链表，设置随机指针
        # 重新把curNode指针挪到对应位置（copy还在Node(0)，所以是下一个）
        curNode = copy.next
        while curNode is not None:
            if curNode.random is not None:
                # 从hash-map里面找随机指针应该指向的对应新node
                curNode.random = randomPointerMap[curNode.random]
            curNode = curNode.next
        
        return copy.next
```

### Jun 16, 2020

又做一遍这个题，更新一个递归解法：

既然每个node有两个链指针，那就分别对两个链指针做递归，设置个 hash map 储存已经复制好的node（本质上还是需要借助hash map 来联系新旧的链表）。

```python
class Solution:
    def __init__(self):
        self.visited = dict()
        
    def copyRandomList(self, head):
        # 到链表结尾就是None，就停止
        if not head: return None
        # 已经复制过的就可以直接return
        if head in self.visited: return self.visited[head]
        
        new = Node(head.val)
        self.visited[head] = new
        
        # 设置两个recursion
        new.next = self.copyRandomList(head.next)
        new.random = self.copyRandomList(head.random)
        
        return new
```
