这五道题全部都是和树的遍历有关系,也是非递归的二叉树遍历写法,有前中后序三种遍历,按层遍历。总结如下。
算法思路:二叉树的前序遍历和中序遍历代码基本一致,不同的地方在于什么时候该访问父节点。非递归的写法主要是使用一个栈来保存已经访问过的结点,其实树的前中后序三种遍历就是深度优先搜索的变形。
具体的来说,中序遍历一直将访问到的结点入栈,继续访问该结点的左子结点,直到左子结点为空,弹出栈顶结点,访问。
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
seq = []
stack = []
if root is None:
return seq
while((root is not None) | (len(stack) > 0)):
if root is not None:
stack.append(root)
root = root.left
else:
root = stack.pop()
seq.append(root.val)
root = root.right
return seq
算法思路:前序遍历就是先访问该节点,然后再将该节点的左子节点入栈,如果该节点为空,则弹出栈顶元素,访问右子结点。
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
seq = []
stack = []
if root is None:
return seq
while((root is not None) | (len(stack) > 0)):
if root is not None:
seq.append(root.val)
stack.append(root)
root = root.left
else:
root = stack.pop()
root = root.right
return seq
算法思路:由于后序遍历是先访问左子结点,再访问右子节点,最后是根节点。但是如果我们按根节点,右子节点,左子节点的顺序访问,然后最后反转过来。
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
seq = []
stack = []
if root is None:
return seq
while((root is not None)|(len(stack) > 0 )):
if root is not None:
seq.append(root.val) # first visit root node
stack.append(root)
root = root.right # second visit rightchild node
else:
root = stack.pop()
root = root.left # third visit leftchild node
# beacause we visit by order that root,rightchild,left,
# so we should reverse the final result
return seq[::-1]
算法思路:二叉树的层次遍历实际上是广度优先搜索,在树的搜索过程中,每次都要搜索完该层然后再进入下一层,广度优先搜索的的广度就体现在树的每一层上。树的层次遍历,我们需要用一个队列来保存当前结点的左右子结点,每次从队列中存储的第一个元素出队,访问该结点,判断是否有左右子结点,如果有就入队,当队列为空则结束了遍历。
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
list = []
seq = []
if root is None:
return seq
list.append(root)
while(len(list) > 0):
temp = []
length_layer = len(list)
for i in range(length_layer):
root = list[0]
temp.append(root.val)
del list[0]
if root.left is not None:
list.append(root.left)
if root.right is not None:
list.append(root.right)
seq.append(temp)
return seq
算法思路:这道题和上面那道题非常相似,唯一需要注意的地方在于偶数层的结点应该从右到左访问,奇数层的结点应该从左到右访问。所以我们可以设置一个额外的列表来保存偶数层的结点,在代码中就是temp_list,它的左右在于将偶数层的结点反转过来,然后访问temp_list中的结点。这里值得注意的是:我们不能够在访问temp_list的结点时候,顺便将该结点的左右子结点入队,这会导致下一层的访问又是从右到左的访问顺序,我们应该按原来树的每一层结构顺序,将结点的左右子结点入队,而不是按反转过来的结点顺序,将结点的左右子结点入队。我在这里被坑了一个小时,我的天。
class Solution:
def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
seq = []
list = []
if root is None:
return seq
list.append(root)
layer = 0
while(len(list) > 0):
temp = []
if layer % 2 == 0:
length_layer = len(list)
for i in range(length_layer):
root = list[0]
temp.append(root.val)
del list[0]
if root.left is not None:
list.append(root.left)
if root.right is not None:
list.append(root.right)
seq.append(temp)
layer += 1
elif layer % 2 == 1:
length_layer = len(list)
temp_list = list[::-1]
for i in range(length_layer):
root = temp_list[0]
temp.append(root.val)
del temp_list[0]
root = list[0]
del list[0]
if root.left is not None:
list.append(root.left)
if root.right is not None:
list.append(root.right)
seq.append(temp)
layer += 1
return seq