forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clone-binary-tree-with-random-pointer.py
148 lines (124 loc) · 3.98 KB
/
clone-binary-tree-with-random-pointer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Time: O(n)
# Space: O(h)
# Definition for Node.
class Node(object):
def __init__(self, val=0, left=None, right=None, random=None):
self.val = val
self.left = left
self.right = right
self.random = random
# Definition for NodeCopy.
class NodeCopy(object):
def __init__(self, val=0, left=None, right=None, random=None):
pass
class Solution(object):
def copyRandomBinaryTree(self, root):
"""
:type root: Node
:rtype: NodeCopy
"""
def iter_dfs(node, callback):
result = None
stk = [node]
while stk:
node = stk.pop()
if not node:
continue
left_node, copy = callback(node)
if not result:
result = copy
stk.append(node.right)
stk.append(left_node)
return result
def merge(node):
copy = NodeCopy(node.val)
node.left, copy.left = copy, node.left
return copy.left, copy
def clone(node):
copy = node.left
node.left.random = node.random.left if node.random else None
node.left.right = node.right.left if node.right else None
return copy.left, copy
def split(node):
copy = node.left
node.left, copy.left = copy.left, copy.left.left if copy.left else None
return node.left, copy
iter_dfs(root, merge)
iter_dfs(root, clone)
return iter_dfs(root, split)
# Time: O(n)
# Space: O(h)
class Solution_Recu(object):
def copyRandomBinaryTree(self, root):
"""
:type root: Node
:rtype: NodeCopy
"""
def dfs(node, callback):
if not node:
return None
left_node, copy = callback(node)
dfs(left_node, callback)
dfs(node.right, callback)
return copy
def merge(node):
copy = NodeCopy(node.val)
node.left, copy.left = copy, node.left
return copy.left, copy
def clone(node):
copy = node.left
node.left.random = node.random.left if node.random else None
node.left.right = node.right.left if node.right else None
return copy.left, copy
def split(node):
copy = node.left
node.left, copy.left = copy.left, copy.left.left if copy.left else None
return node.left, copy
dfs(root, merge)
dfs(root, clone)
return dfs(root, split)
# Time: O(n)
# Space: O(n)
import collections
class Solution2(object):
def copyRandomBinaryTree(self, root):
"""
:type root: Node
:rtype: NodeCopy
"""
lookup = collections.defaultdict(lambda: NodeCopy())
lookup[None] = None
stk = [root]
while stk:
node = stk.pop()
if not node:
continue
lookup[node].val = node.val
lookup[node].left = lookup[node.left]
lookup[node].right = lookup[node.right]
lookup[node].random = lookup[node.random]
stk.append(node.right)
stk.append(node.left)
return lookup[root]
# Time: O(n)
# Space: O(n)
import collections
class Solution2_Recu(object):
def copyRandomBinaryTree(self, root):
"""
:type root: Node
:rtype: NodeCopy
"""
def dfs(node, lookup):
if not node:
return
lookup[node].val = node.val
lookup[node].left = lookup[node.left]
lookup[node].right = lookup[node.right]
lookup[node].random = lookup[node.random]
dfs(node.left, lookup)
dfs(node.right, lookup)
lookup = collections.defaultdict(lambda: NodeCopy())
lookup[None] = None
dfs(root, lookup)
return lookup[root]