二叉树专题,重点掌握后续的递归和中间节点的处理。
本题在前一章已经解决了层序遍历的解法,现在来聊一下递归法。
首先需要明确两个概念:深度和高度。(注意,起始位置的值都是1)
深度:从root开始,到当前位置所在节点的层数;
高度:从底层叶子节点开始,到当前所在节点的层数。
再来说一下选择什么顺序来遍历。
前序:从root出发,直接找的是深度;
后序:从叶子节点出发,返回给root节点高度。
也就是说,不管选择哪一种,中间节点都是单独处理的。
按照递归的书写三部曲,可以写出后序遍历的方法。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 后序遍历(Version 1)
# step1 确定返回值类型:TreeNode
# step2 确定终止条件:当前节点是空
if not root:
return 0
else:
# step3 单层处理:按照“左右中”的顺序,先遍历左节点高度,再遍历右节点高度,汇总到中间节点取较大值,再加1(因为当前中间节点也算作一层)
left_height = self.maxDepth(root.left)
right_height = self.maxDepth(root.right)
return max(left_height, right_height) + 1
# 精简递归(Version 2)
return 0 if not root else max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
要麻烦很多,还涉及到回溯算法,十分甚至九分的不推荐。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 递归(前序遍历)
res = 0
if not root:
return 0
self.getdepth(root, 1)
return res
def getdepth(self, node, depth):
res = max(depth, res)
if node.left == None and node.right == None:
return
if node.left:
depth += 1
self.getdepth(node.left, depth)
depth -= 1 # 回溯算法
if node.right:
depth += 1
self.getdepth(node.right, depth)
depth -= 1
return
和上面相似的一道题,只用了递归+左右中的后序遍历。
只需要用for遍历所有孩子节点(其实就是上面分别判断左节点和右节点的推广)。
"""
# Definition for a Node.
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution(object):
def maxDepth(self, root):
"""
:type root: Node
:rtype: int
"""
if not root:
return 0
max_depth = 1 # 在排除顶部节点是空的时候初始化最大值是1
# 遍历所有的孩子节点
for child in root.children:
# 注意在每次比较的时候+ 1,表示计算上了中间节点
max_depth = max(self.maxDepth(child) + 1, max_depth)
return max_depth
本题需要注意的是和上面求解最大值需要遍历到底不一样,本题需要遍历到第一个叶子节点,也就是左右子树都没有的第一个节点。
依然使用后序遍历。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 递归法
if not root:
return 0
else:
# 左
left_height = self.minDepth(root.left)
# 右
right_height = self.minDepth(root.right)
# 中
if root.left and root.right == None: # 左子树存在,右子树不存在
return left_height + 1
if root.right and root.left == None: # 右子树存在左子树不存在
return right_height + 1
# 遇到叶子节点返回到中间节点的最小值
return min(left_height, right_height) + 1
把求解左右高度的简化到中间处理的返回值处。
# 左
left_height = self.minDepth(root.left)
# 右
right_height = self.minDepth(root.right)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 当作普通二叉树
if not root:
return 0
# 左
left_num = self.countNodes(root.left)
# 右
right_num = self.countNodes(root.right)
# 中
return left_num + right_num + 1
# 精简版
if not root:
return 0
return self.countNodes(root.left) + self.countNodes(root.right) + 1
题干当中还特别说明了是完全二叉树,所以我们可以使用完全二叉树在左右外侧深度相等的时候是满二叉树的性质来统计。
简单概括就是:如果这一层的左子树的左深度和右子树的右深度相等,那么就可以判断现在这是满二叉树。
利用这个性质,我们就很容易可以判断满足满二叉树的条件。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 利用完全二叉树
if not root:
return 0
# 判断是满二叉树直接输出
leftnode = root.left
rightnode = root.right
left_depth, right_depth = 0, 0
while leftnode:
leftnode = leftnode.left
left_depth += 1
while rightnode:
rightnode = rightnode.right
right_depth += 1
if left_depth == right_depth:
return (2 << left_depth) - 1 # 2 << 1 = 2 ^ 2
# 普通二叉树正常递归输出
return self.countNodes(root.left) + self.countNodes(root.right) + 1
第16天完结