LeetCode 剑指Offer 数据结构之 树 总结 Part1
经典问题
1)遍历
2)树深度
3)重建树
4)对称树
5)子树匹配
6)二叉查找树
遍历问题
对应的题目是剑指 Offer 32 - I,剑指 Offer 32 - II,剑指 Offer 32 - III,剑指 Offer 34
DFS(一般采用递归) 深度优先的遍历
三种:
先序 根 左 右
(目前感觉用DFS先序走起比较多)
def preorderTraversal(root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return [root.val] + preorderTraversal(root.left) + preorderTraversal(root.right)
中序 左 根 右
(目前感觉中序用的多,主要在二叉查找树里,最大作用是把二叉查找树转化为一个有序队列)
def inorderTraversal(root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return inorderTraversal(root.left) + [root.val] + inorderTraversal(root.right)
后序 左 右 根
def lastorderTraversal(root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
return lastorderTraversal(root.left) + lastorderTraversal(root.right) + [root.val]
总结:二叉树的递归遍历是自上而下的过程 出口为到叶子节点 连带了空树特例 比较好理解
BFS(一般利用队列) 广度优先的遍历
特点是层级明显,众多二叉树非递归解法的雏形套路……
def LevelOrder(node):
if node == None:
return
stack = []
stack.append(node)
while stack != []:
node = stack.pop(0)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
print(node.val)
以上为直接print 根据该print序列是无法还原树的,穿过叶子节点需要print null以还原树,后续会进行总结
该方式也比较容易改成按层,每层一个list的方式进行遍历,同时也很好做树的最大深度问题
‘’’
可以借助队列先进先出的特点,
①每次取对头节点的值放入结果中
②按照先序遍历每次先将根节点存入,再依次存入其左孩子右孩子(如果有的话)
以上两点在while循环中实现,直至队列长度为0
‘’’
def PrintTree(pRoot):
'''
按层从左到右打印tree
:param pRoot:
:return:
'''
if pRoot is None:
return []
if pRoot.left is None and pRoot.right is None:
return [[pRoot.val]]
stack = [pRoot]
output = []
while (stack): # 下一层要打印的根
temp = []
for i in range(len(stack)):
out_node = stack.pop(0) # 先进先出
temp.append(out_node.val)
if out_node.left is not None:
stack.append(out_node.left) # 这个头结点的左孩子 放入下一层要打印的stack里
if out_node.right is not None:
stack.append(out_node.right) # 这个头结点的右孩子 放入下一层要打印的stack里
output.append(temp)
return output
细节在于要遍历打印本层所有节点同时将这些节点的孩子节点放入队列,需要使用:range(len(stack)),因为队列pop后长度会变
下一部分将总结二叉树深度的相关问题