二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数。深度从1开始,则根节点的深度为1。使用前序遍历,从上往下求深度。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数。高度从1开始,则叶子节点的高度为1。使用后序遍历,从下往上求高度。
题目链接:二叉树的最大深度
解法:
根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。之所以不通过叶子节点的高度来求,是因为叶子节点有很多吧。
递归法:对于当前节点,首先计算左节点的高度,再计算右节点的高度,那么当前节点的高度就是二者的最大值再加一。
迭代法:迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
边界条件:无
时间复杂度:O(n)
空间复杂度:
递归法:
O(height),其中 height 表示二叉树的高度。递归函数需要栈空间,而栈空间取决于递归的深度,因此空间复杂度等价于二叉树的高度。
迭代法:O(n)。
# 后序遍历,递归法
# 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
"""
if not root:
return 0
left_height = self.maxDepth(root.left)
right_height = self.maxDepth(root.right)
return 1 + max(left_height, right_height)
# 层序遍历,迭代法
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
import collections
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
queue = collections.deque([root])
depth = 0
while queue:
for _ in range(len(queue)):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
depth += 1
return depth
题目链接:n叉树的最大深度
解法:
和二叉树的类似,只是通过一个for循环遍历同一层的所有孩子节点。
边界条件:无
时间复杂度:O(n)
空间复杂度:
递归法:O(height)
迭代法:O(n)
# 递归法
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
if root.children:
for child in root.children:
max_depth = max(max_depth, self.maxDepth(child) + 1)
return max_depth
# 层序遍历,队列,迭代法
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
import collections
class Solution(object):
def maxDepth(self, root):
"""
:type root: Node
:rtype: int
"""
if not root:
return 0
queue = collections.deque([root])
max_depth = 0
while queue:
max_depth += 1
for _ in range(len(queue)):
node = queue.popleft()
if node.children:
for child in node.children:
queue.append(child)
return max_depth
题目链接:二叉树的最小深度
解法:
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意一定是到叶子节点。左右孩子都为空的节点才是叶子节点!
如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
递归法:和上面的思路一致,照着就能写出来。
迭代法:主要是注意返回的终止条件,是队列中的某个节点没有左右孩子的时候,就返回记录的深度。
边界条件:无
时间复杂度:O(n)
空间复杂度:
递归法:O(height)
迭代法:O(n)
# 递归法
# 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
min_depth = 0
if not root.left:
min_depth = 1 + self.minDepth(root.right)
elif not root.right:
min_depth = 1 + self.minDepth(root.left)
else:
min_depth = 1 + min(self.minDepth(root.left),
self.minDepth(root.right))
return min_depth
# 层序遍历,迭代法
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
import collections
class Solution(object):
def minDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
min_depth = 0
queue = collections.deque([root])
while queue:
min_depth += 1
for _ in range(len(queue)):
node = queue.popleft()
# 如果一个节点,已经没有子节点,那就是从这终止计算
if not node.left and not node.right:
return min_depth
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return min_depth
题目链接:完全二叉树的节点个数
解法:
首先区别满二叉树和完全二叉树,以更好的理解完全二叉树。
满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
看到这里,发现这个题目其实有点麻烦,这些概念太容易混淆了。
这个题可以首先不考虑完全二叉树的特性,用基础的方法去求解,递归法和迭代法。
利用完全二叉树的特性:那么左子树的深度等于右子树的深度时,满二叉树,根据公式来计算;否则递归,直到最后一定会满足左孩子或右孩子为满二叉树的情况。用递归来实现。
边界条件:无
时间复杂度:
利用完全二叉树的特性:O(logn * logn)
空间复杂度:O(logn)
# 基础版,递归法
# 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_node = self.countNodes(root.left)
right_node = self.countNodes(root.right)
return 1 + left_node + right_node
# 基础版,迭代法
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
import collections
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
queue = collections.deque([root])
node_number = 0
while queue:
for _ in range(len(queue)):
node = queue.popleft()
node_number += 1
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return node_number
# 利用完全二叉树的特性,递归
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
import collections
class Solution(object):
def countNodes(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
# 先计算左子树的深度和右子树的深度
left_depth = 0
right_depth = 0
left = root.left
right = root.right
while left:
left_depth += 1
left = left.left
while right:
right_depth += 1
right = right.right
# 如果是完全二叉树且左子树深度等于右子树深度,则是满二叉树
# 注意,根节点的深度为左子树的深度加1
if left_depth == right_depth:
return 2 ** (left_depth+1) - 1
return 1 + self.countNodes(root.left) + self.countNodes(root.right)