最大深度问题
二叉树的深度:根节点到最远叶子节点的最长路径上的节点数
叶子节点:没有子节点的节点
LeetCode104
https://leetcode.cn/problems/maximum-depth-of-binary-tree/
思路分析
方法1:递归(后序遍历)
最大深度 depth = 1+max(leftDepth, rightDepth),可以用递归实现;递归结束条件 node == null 返回0;先拿到左右子树的结果再计算总的结果,可以看做是后序遍历的扩展问题
int leftDepth = getDepth(node.left); //左
int rightDepth = getDepth(node.right); //右
int depth = 1+max(leftDepth, rightDepth); //中
方法2:层序遍历
如果确定了树最大有几层,也就知道最大深度了。套用层序遍历的代码。
代码实现
方法1:递归(后序遍历)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 方法1:递归(后序遍历)
if not root:
return 0
left_depth = self.maxDepth(root.left)
right_depth = self.maxDepth(root.right)
return 1+max(left_depth, right_depth)
方法2:层序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 方法2:层序遍历
if not root:
return 0
queue = collections.deque([root])
depth = 0
while queue:
# 当前层的节点数
n = len(queue)
for i in range(n):
node = queue.pop()
if node.left:
queue.appendleft(node.left)
if node.right:
queue.appendleft(node.right)
depth += 1
return depth
判断平衡树
LeetCode110
https://leetcode.cn/problems/balanced-binary-tree/
高度平衡二叉树:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1
高度和深度的定义
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数
注:这里的定义有不同的标准,LeetCode以节点数为准,根节点的深度为1,叶子节点的高度为1
思路分析
方法1:获取所有节点再判断
获取节点的高度
- 如果节点为空,高度为0
- 如果节点非空,节点高度为 左右子树中最大高度加1 max(left, right)+1
判断是否是高度平衡二叉树
- 如果节点为空,是
- 如果节点不为空,判断所有节点的左右子树高度差绝对值是否都不超过1
方法2:一边获取高度,一边判断
获取节点的高度
- 如果节点为空,高度为0
- 如果节点非空,节点高度为 左右子树中最大高度加1 max(left, right)+1
- 若节点左子树/右子树为非高度平衡二叉树,则其高度返回 -1 (标志位),只要子树中有非高度平衡二叉树,其父/祖节点高度就为 -1 (标志位),只要子树中有非高度平衡二叉树,该二叉树就不是高度平衡二叉树
判断是否是高度平衡二叉树
- 如果节点为空,是
- 如果节点不为空,判断所有节点的左右子树高度差绝对值是否都不超过1
代码实现
方法1:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
# 获取节点高度
def height(node):
if not node:
return 0
left_height = height(node.left)
right_height = height(node.right)
return max(left_height, right_height)+1
if not root:
return True
# 注意:这里是每个节点都要满足条件
return abs(height(root.left)-height(root.right)) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right)
方法2:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
def height(node):
if not node:
return 0
left_height = height(node.left)
right_height = height(node.right)
if left_height == -1 or right_height == -1 or abs(left_height-right_height) > 1:
return -1
else:
return max(left_height, right_height)+1
return height(root) >= 0
最小深度问题
LeetCode111
https://leetcode.cn/problems/minimum-depth-of-binary-tree/
思路分析
说明:叶子节点是指没有子节点的节点。前两个题都涉及最大深度,那将max改成min能不能解决问题呢?不行,注意下图
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。最小深度的一层必须要有叶子节点,因此不能直接用
方法1:递归
核心:
- 如果左子树为空,右子树非空,最小深度为右子树最小深度+1
- 如果左子树非空,右子树为空,最小深度为左子树最小深度+1
- 如果左子树和右子树都非空,最小深度为左右子树最小深度最小值+1
方法2:层次遍历
遍历时,第一次遇到叶子就直接返回其所在的层次即可
代码实现
方法1:递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
elif not root.left and not root.right:
return 1
elif root.left and root.right:
return min(self.minDepth(root.left), self.minDepth(root.right)) + 1
elif root.left:
return self.minDepth(root.left) + 1
elif root.right:
return self.minDepth(root.right) + 1
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
# 代码改进优化
if not root:
return 0
if not root.left and not root.right:
return 1
min_depth = 10**9
if root.left:
min_depth = min(self.minDepth(root.left), min_depth)
if root.right:
min_depth = min(self.minDepth(root.right), min_depth)
return min_depth + 1
方法2:层次遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
# 方法2:层次遍历
if not root:
return 0
queue = collections.deque([root])
level = 1
while queue:
for i in range(len(queue)):
node = queue.pop()
if not node.left and not node.right:
return level
if node.left:
queue.appendleft(node.left)
if node.right:
queue.appendleft(node.right)
level += 1
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
# 方法2:层次遍历
if not root:
return 0
queue = collections.deque([(root, 1)])
while queue:
node, depth = queue.pop()
if not node.left and not node.right:
return depth
if node.left:
queue.appendleft((node.left, depth+1))
if node.right:
queue.appendleft((node.right, depth+1))
N叉数的最大深度
LeetCode559
https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/
思路分析
将二叉树换成了N叉数,不同点就在于N叉数的节点比较多,使用List存,最大的区别是处理子树时加了个处理List的for循环
可用递归和层次遍历解决
代码实现
方法1:递归
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
# 方法1:递归
if not root:
return 0
if not root.children:
return 1
return max([ self.maxDepth(node) for node in root.children]) + 1
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
# 方法1:递归(代码简化)
return max([ self.maxDepth(node) for node in root.children], default=0) + 1 if root else 0
方法2:层次遍历
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
# 方法2:层次遍历
if not root:
return 0
queue = collections.deque([root])
level = 0
while queue:
for i in range(len(queue)):
node = queue.pop()
for j in node.children:
queue.appendleft(j)
level += 1
return level