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

104.二叉树最大深度

深度和高度

  • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
  • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)

前序求的就是深度,用后序求的是高度。

在这里插入图片描述

根节点的深度,其实就是这棵树的最大高度!

  • 整体思路:按照后序遍历左右中的顺序,依次遍历每个节点,把它的高度返回给上一层父节点!最后回到根节点时就掌握了所有节点的高度信息!

递归法

递归三部曲:

  • 确定递归函数返回值和参数
int getHeight(TreeNode node)
  • 确定终止条件:
if(node == null) return 0;
  • 确定单层递归的逻辑

按照后序遍历左 右 中的顺序依次处理。每次返回给父节点(中)的时候 就代表了当前根节点的最大高度!!

int leftHeight = getHeight(node.left);  //左
int rightHeight = getHeight(node.right);  //右
int maxHeight = 1 + Math.max(leftHeight, rightHeight);

在这里插入图片描述

  • java代码
class Solution {
    public int getHeight(TreeNode node) {  //后序遍历
        if(node == null) return 0;  //结束条件
        int leftHeight = getHeight(node.left);  //左
        int rightHeight = getHeight(node.right);  //右
        int maxHeight = 1 + Math.max(leftHeight, rightHeight);
        return maxHeight;
    }

    public int maxDepth(TreeNode root) {
        return getHeight(root);
    }
}
  • 精简版
class solution {
public int maxDepth(TreeNode root) {
        if (root == null) return 0;
        return 1 + Math.Max(maxDepth(root.left), maxDepth(root.right));
    }
};

559.n叉树的最大深度

把左和右递归遍历的操作放到一个for循环里,遍历node.children 得到depth,最后return depth+1即可!

class Solution {
    public int getHeight(Node node) {
        if(node == null) return 0;
        int depth = 0;
        for(Node cur : node.children) {
            depth = Math.max(depth, getHeight(cur));
        }
        return 1 + depth;
    }

    public int maxDepth(Node root) {
        return getHeight(root);
    }
}

111.二叉树最小深度

前序遍历和后序遍历都可以,前序求的是深度,后序求的是高度。这里我们用后序。

明确题目定义!叶子节点是指左右孩子都为null的节点,因此我们在计算depth时就要添加条件判断,分别判断左为空右不为空左不为空右为空左右都不空的情况来计算当前最小深度!

后序遍历是左右中,从最底层开始一层层往上传递到根节点。

在这里插入图片描述

后序 递归

递归三部曲:

  • 确定递归函数返回值和参数
int getHeight(TreeNode node)
  • 确定终止条件:
if(node == null) return 0;
  • 确定单层递归的逻辑

分成三种情况:左为空右不为空左不为空右为空左右都不空。然后return 接收到的最小高度+1

int leftHeight = getHeight(node.left);
        int rightHeight = getHeight(node.right);
        if(node.right == null && node.left != null) return 1 + leftHeight;
        else if(node.left == null && node.right != null) return 1 + rightHeight;
        else {  //左右都不为空
            return 1 + Math.min(leftHeight, rightHeight);
        }
  • java代码
class Solution {
    int getHeight(TreeNode node) {
        if(node == null) return 0;
        int leftHeight = getHeight(node.left);
        int rightHeight = getHeight(node.right);
        if(node.right == null && node.left != null) return 1 + leftHeight;
        else if(node.left == null && node.right != null) return 1 + rightHeight;
        else {  //左右都不为空
            return 1 + Math.min(leftHeight, rightHeight);
        }
    }

    public int minDepth(TreeNode root) {
        return getHeight(root);
    }
}

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

普通做法

直接把它当成是一棵普通二叉树,遍历的过程中记录节点数量。递归的话还是用后序(左右中)

  • 时间复杂度:O(n)
  • 空间复杂度:O(log n),算上了递归系统栈占用的空间

完全二叉树做法

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

对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。

在这里插入图片描述

我们能不能利用完全二叉树的特性,不要去遍历所有的节点呢?只遍历一部分节点就能判断?

  • 核心思路:利用完全二叉树特性,因为题目是完全二叉树,直接全部遍历左孩子和右孩子,如果高度相等它就是满二叉树,直接return 2^树深度 - 1个节点。内侧的节点就不用遍历了!

  • 在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。

递归三部曲

终止条件:==null或者为满二叉树的情况

 //终止条件
        if(root == null) return 0;
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftHeight = 0, rightHeight = 0;  //计数从0开始
        while(left != null) {
            left = left.left;
            leftHeight += 1;
        } 
        while(right != null) {
            right = right.right;
            rightHeight += 1;
        }
        if(leftHeight == rightHeight) return (2 << leftHeight) - 1; 
  • 单层递归逻辑
return countNodes(root.left) + countNodes(root.right) + 1;
  • 完整代码
class Solution {
    public int countNodes(TreeNode root) {
        //终止条件
        if(root == null) return 0;
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftHeight = 0, rightHeight = 0;  //计数从0开始
        while(left != null) {
            left = left.left;
            leftHeight += 1;
        } 
        while(right != null) {
            right = right.right;
            rightHeight += 1;
        }
        if(leftHeight == rightHeight) return (2 << leftHeight) - 1; 
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
  • 时间复杂度:O(log n × log n)
  • 空间复杂度:O(log n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值