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

104. 二叉树的最大深度

题目链接 | 解题思路

  • 深度:从根节点到该节点的最长简单路径边的条数(深度从0开始)或者节点数(深度从1开始)
    • 深度从根节点开始计算,子节点深度取决于父节点的深度,信息的流向决定了使用前序遍历
  • 高度:从该节点到叶子节点的最长简单路径边的条数(深度从0开始)或者节点数(高度从1开始)
    • 高度从叶子节点开始计算,父节点的高度取决于子节点的高度,信息的流向决定了使用后序遍历

高度与深度的联系:根节点的高度就是二叉树的最大深度

在这里插入图片描述

前序遍历(自己的解法:深度)

class Solution:
    def depth(self, node: Optional[TreeNode], level: int) -> int:
        if node == None:
            return level
        # middle
        left_depth = self.depth(node.left, level + 1)		# left
        right_depth = self.depth(node.right, level + 1)		# right
        return max(left_depth, right_depth)

    def maxDepth(self, root: Optional[TreeNode]) -> int:
        return self.depth(root, 0)

后序遍历(高度)

class Solution:
    def height(self, node: Optional[TreeNode]) -> int:
        if node == None:
            return 0
        left_height = self.height(node.left)			# left
        right_height = self.height(node.right)			# right
        return max(left_height, right_height) + 1		# middle

    def maxDepth(self, root: Optional[TreeNode]) -> int:
        return self.height(root)

559. n叉树的最大深度

题目链接

自己的前序遍历解法,和二叉树的几乎一模一样。

class Solution:
    def depth(self, node: 'Node', level: int) -> int:
        if node == None:
            return level
        records = [level + 1]
        for child in node.children:
            records.append(self.depth(child, level + 1))
        return max(records)

    def maxDepth(self, root: 'Node') -> int:
        return self.depth(root, 0)

111. 二叉树的最小深度

题目链接 | 解题思路

最小深度:从根节点叶子节点的最短路径上的节点数量。(注意是叶子节点!!)
这个定义和根节点的高度非常相似(高度是根节点到叶子节点的最远路径),所以还是可以后序遍历,从而得到最小深度。相比于前序,后序的解法会稍简洁一些。

要小心的是对于空节点的处理,在后序解法中 None 是没可能成为叶子节点的,但却拥有最小的深度。

前序遍历(自己的解法:深度)

class Solution:
    def depth(self, node: Optional[TreeNode], level: int, records: list) -> None:
        if node.left == None and node.right == None:
            records.append(level + 1)
        if node.left != None:
            self.depth(node.left, level + 1, records)
        if node.right != None:
            self.depth(node.right, level + 1, records)

    def minDepth(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        records = []
        self.depth(root, 0, records)
        return min(records)

后序遍历(根节点的最小“高度“)

class Solution:
    def height(self, node: Optional[TreeNode]) -> int:
        if node == None:
            return 0
        left_height = self.height(node.left)				# left
        right_height = self.height(node.right)				# right
        # middle
        if node.left != None and node.right == None:        # exclude the "None" node
            return 1 + left_height							
        if node.left == None and node.right != None:
            return 1 + right_height							
        return 1 + min(left_height, right_height)			


    def minDepth(self, root: Optional[TreeNode]) -> int:
        return self.height(root)

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

题目链接 | 解题思路

看似非常模板化的一道题,任何遍历方式都能够得到所有节点然后计数。但题目要求优于 O ( n ) O(n) O(n) 的算法,就必须利用完全二叉树的特征:除了最后一层都是满的,最后一层的节点尽可能靠左分布。

对于完全二叉树而言,寻找到满二叉子树即可通过公式直接计算该树内的节点数量,并向父节点传递。只需要得到左右外侧的深度即可判断,单次搜索的复杂度为 O ( log ⁡ n ) O(\log{n}) O(logn)。对于非满二叉子树,递归会逐渐将其拆成若干满二叉子树和单独节点。

这道题的递归终止条件比较复杂,当找到了满二叉子树的时候也应该直接返回(这也是低复杂度的来源,跳过了搜索所有满二叉子树的内部节点)。

  • 时间复杂度: O ( log ⁡ n × log ⁡ n ) O(\log{n} \times \log{n}) O(logn×logn)
  • 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn)
class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:
        if root == None:
            return 0
        
        # check whether this (sub)tree is full
        left_depth = right_depth = 0
        left_node = root.left
        right_node = root.right
        while (left_node != None):
            left_node = left_node.left
            left_depth += 1
        while (right_node != None):
            right_node = right_node.right
            right_depth += 1
        # full tree case: directly return
        if left_depth == right_depth:               
            return (2**(left_depth+1)) - 1				# equivalent to (2<<left_depth) - 1, fancy!
        # not a full tree, go into recursion
        print("haha")
        return self.countNodes(root.left) + self.countNodes(root.right) + 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值