forked from ls1248659692/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary_tree.py
More file actions
204 lines (167 loc) · 5.17 KB
/
Copy pathbinary_tree.py
File metadata and controls
204 lines (167 loc) · 5.17 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# Classification: binary tree, complete binary tree, full binary tree, binary search tree, AVL tree(self-balancing)
#
# Time: O(n)
# Space: O(h) h: height of tree
from collections import deque
# Definition for a binary tree node
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
'''
traverse binary tree recursively
'''
# pre-order: root->left->right
def preorder_traversal_recursively(self, root: 'TreeNode'):
# recursion terminator here
# you can check if none when add left and right child, it will decrease one recursion depth,
# but you have to check whether root is None outside.
if not root:
return
'''
add current node logic here
'''
self.process_logic(root)
self.preorder_traversal_recursively(root.left)
self.preorder_traversal_recursively(root.right)
# in-order: left->root->right
def inorder_traversal_recursively(self, root: 'TreeNode'):
if not root:
return
self.inorder_traversal_recursively(root.left)
'''
add current node logic here
'''
self.process_logic(root)
self.inorder_traversal_recursively(root.right)
# post-order: left->right->root
def postorder_traversal_recursively(self, root: 'TreeNode'):
if not root:
return
self.postorder_traversal_recursively(root.left)
self.postorder_traversal_recursively(root.right)
'''
add current node logic here
'''
self.process_logic(root)
# level-order
# to traverse recursively, need help from extra data structure or dfs level by level
def level_order_traversal_recursively(self, root: 'TreeNode') -> 'List[List[int]]':
res = []
def dfs(root, level):
if not root:
return
if len(res) < level + 1:
res.append([])
'''
add current node logic here
'''
self.process_logic(root)
res[level].append(root.val)
dfs(root.left, level + 1)
dfs(root.right, level + 1)
dfs(root, 0)
return res
'''
traverse binary tree iteratively
'''
# There are too many version to traverse iteratively, just choose the one you like it.
# pre-order: root->left->right
def preorder_traversal_iteratively(self, root: 'TreeNode'):
if not root:
return []
stack = [root]
while stack:
root = stack.pop()
'''
add current node logic here
'''
self.process_logic(root)
# push right child first because of FILO
if root.right:
stack.append(root.right)
if root.left:
stack.append(root.left)
# in-order: left->root->right
def inorder_traversal_iteratively(self, root: 'TreeNode'):
stack = []
# keep stack empty and compare root too, compatible with edge case: root=None
while stack or root:
# push itself and all left children into stack iteratively
while root:
stack.append(root)
root = root.left
root = stack.pop()
'''
add current node logic here
'''
self.process_logic(root)
# point to right child
root = root.right
# here I choose to not use
# post-order: left->right->root
def postorder_traversal_iteratively(self, root: 'TreeNode'):
if not root:
return []
stack = [root]
# used to record whether left or right child has been visited
last = None
while stack:
root = stack[-1]
# if current node has no left right child, or left child or right child has been visited, then process and pop it
if not root.left and not root.right or last and (root.left == last or root.right == last):
'''
add current node logic here
'''
self.process_logic(root)
stack.pop()
last = root
# if not, push right and left child in stack
else:
# push right first because of FILO
if root.right:
stack.append(root.right)
if root.left:
stack.append(root.left)
# post-order: left->right->root
# use visit flag
def postorder_traversal_iteratively2(self, root: 'TreeNode'):
if not root:
return []
stack = [root]
while stack:
root = stack[-1]
# use visited attribute to judge whether it has been visited
if hasattr(root, 'visited'):
'''
add current node logic here
'''
self.process_logic(root)
stack.pop()
del root.visited
else:
if root.right:
stack.append(root.right)
if root.left:
stack.append(root.left)
root.visited = True
# level-order
def level_order_traversal_iteratively(self, root: 'TreeNode'):
if not root:
return []
queue = deque([root])
while queue:
for _ in range(len(queue)):
cur = queue.popleft()
'''
add current node logic here
'''
self.process_logic(cur)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
'''
add level logic here if you need
'''