代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数。深度从1开始,则根节点的深度为1。使用前序遍历,从上往下求深度。 

二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数。高度从1开始,则叶子节点的高度为1。使用后序遍历,从下往上求高度。

104.二叉树的最大深度

题目链接:二叉树的最大深度

解法:

根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。之所以不通过叶子节点的高度来求,是因为叶子节点有很多吧。

递归法:对于当前节点,首先计算左节点的高度,再计算右节点的高度,那么当前节点的高度就是二者的最大值再加一。

迭代法:迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。

边界条件:

时间复杂度: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

559.n叉树的最大深度

题目链接: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

111.二叉树的最小深度

题目链接:二叉树的最小深度

解法:

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意一定是到叶子节点。左右孩子都为空的节点才是叶子节点!

代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数_第1张图片

如果左子树为空,右子树不为空,说明最小深度是 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

222.完全二叉树的节点个数

题目链接:完全二叉树的节点个数

解法:

首先区别满二叉树和完全二叉树,以更好的理解完全二叉树。

满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。

代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数_第2张图片

完全二叉树:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。

代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数_第3张图片

完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。

对于情况一,可以直接用 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)

你可能感兴趣的:(数据结构和算法,算法,数据结构)