代码改变世界

[LeetCode] 138. Copy List with Random Pointer_Medium tag: Linked List

2019-05-04 11:06  Johnson_强生仔仔  阅读(210)  评论(0编辑  收藏  举报

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.

 

Example 1:

Input:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

Explanation:
Node 1's value is 1, both of its next and random pointer points to Node 2.
Node 2's value is 2, its next pointer points to null and its random pointer points to itself.

 

Note:

  1. You must return the copy of the given head as a reference to the cloned list.

这个题目有三种做法,

Update 06/23/2021  添加了DFS的做法

note: 注意head.random有可能是None的情况

1. S: O(n)    create一个dictionary,然后先建dictionary和copy list以及next指针。然后再一遍,去建random指针。

2: S: O(1)    利用如下图所示的结构,然后再将copy node和原来的node分开即可。

3. S O(n) 还是利用dictionary, 但是我们利用DFS

Old List: A --> B --> C --> D
InterWeaved List: A --> A' --> B --> B' --> C --> C' --> D --> D'

1. code S:O(n)
class Node:
    def __init__(self, x, next, random):
        self.val = x
        self.next = next
        self.random = random

class Solution:
    def deepCopyList(self, head):
        dummy, listMap = Node(0, None, None), dict()
        head1, head2 = head, dummy
        # copy the list and next pointers
        while head1:
            head2.next = Node(head1.val, None, None)
            ListMap[head1] = head2.next
            head1 = head1.next
            head2 = head2.next
        # copy the random pointers
        head1, head2 = head, dummy.next
        while head1:
            if head1.random: # head1.random can be None
                head2.random = listMap[head1.random]
            head1 = head1.next
            head2 = head2.next
        return dummy.next

 

2. code     S: O(1)

def deepCopyList(self, head):
    dummy = Node(0, None, None)
    dummy.next = head
    # make copy nodes
    while head:
        temp = head.next
        head.next = Node(head.val, None, None)
        head.next.next = temp
        head = temp
    # create random pointers
    head = dummy.next
    while head:
        if head.random:
            head.next.random = head.random.next
        head = head.next.next
    # make copy list and recover the original list
    dummy2 = Node(0, None, None)
    head1, head2 = dummy.next, dummy2
    while head1:
        head2.next = head1.next
        head1.next= head1.next.next
        head1 = head1.next
        head2 = head2.next
    return dummy2.next

 

3. Code S: O(n)

"""
# 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: 'Node') -> 'Node':
        nodeMap = dict()
        return self.dfs(head, nodeMap)

     def dfs(self, node: 'Node', nodeMap: dict) -> 'Node':
        if not node: return 
        if node not in nodeMap:
            newNode = Node(node.val)
            nodeMap[node] = newNode
            newNode.next = self.dfs(node.next, nodeMap)
            newNode.random= self.dfs(node.random, nodeMap)
        return nodeMap[node]