算法第十六天| 二叉树的最大深度 二叉树的最小深度 完全二叉树的节点个数

203 阅读4分钟

前言

今天加油吧

二叉树的最大深度

力扣题目链接(opens new window)

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例: 给定二叉树 [3,9,20,null,null,15,7],

104. 二叉树的最大深度

返回它的最大深度 3 。

思路

这道题求的是深度,换句话来说的最大是多少, 那么就可以使用层序遍历,当遍历完一层后count++就完了。

第二种方法是递归,递归要把注意放在当前执行的事,当我们确定一个节点他的深度的时候,这个节点的深度等于他的左子树的深度加上右子树的深度加1。因为要返回深度所以返回值是int类型。

代码

 /**
 * 递归法
 */
public int maxDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int leftDepth = maxDepth(root.left);
    int rightDepth = maxDepth(root.right);
    return Math.max(leftDepth, rightDepth) + 1;
}
 /**
 * 迭代法,使用层序遍历
 */
public int maxDepth(TreeNode root) {
    if(root == null) {
        return 0;
    }
    Deque<TreeNode> deque = new LinkedList<>();
    deque.offer(root);
    int depth = 0;
    while (!deque.isEmpty()) {
        int size = deque.size();
        depth++;
        for (int i = 0; i < size; i++) {
            TreeNode node = deque.poll();
            if (node.left != null) {
                deque.offer(node.left);
            }
            if (node.right != null) {
                deque.offer(node.right);
            }
        }
    }
    return depth;
}

注意

注意递归是的当前节点处理方法:这个节点的深度=他的左子树的深度+右子树的深度+1

二叉树的最小深度

力扣题目链接(opens new window)

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

111.二叉树的最小深度1

返回它的最小深度 2.

思路

111.二叉树的最小深度

这就重新审题了,题目中说的是:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 ,注意是叶子节点。什么是叶子节点,左右孩子都为空的节点才是叶子节点!

这道题也可以用层次遍历,当判断弹出的元素左右节点都为空则当前的节点就是深度最小的节点。

递归遍历的条件是如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。

反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。

求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。

代码

//递归
public int minDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int leftDepth = minDepth(root.left);
    int rightDepth = minDepth(root.right);
    if (root.left == null) {
        return rightDepth+1;
    }
    if (root.right == null) {
        return leftDepth+1;
    }
/ 左右结点都不为null
    return Math.min(rightDepth,leftDepth)+1;
}

//层次
public int minDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    int min = 0;
    while (!queue.isEmpty()) {
        int len = queue.size();
        min++;
        while (len > 0) {
            TreeNode poll = queue.poll();
            if (poll.left == null && poll.right == null ) 
             // 是叶子结点,直接返回depth,因为从上往下遍历,所以该值就是最小值
                return min;
            }
            if (poll.left != null) {
                queue.add(poll.left);
            }
            if (poll.right != null) {
                queue.add(poll.right);
            }
            len--;
        }

    }
    return min;
}

注意

这道题的递归遍历中 min++要放在层次遍历之前。

完全二叉树的节点个数

力扣题目链接(opens new window)

给出一个完全二叉树,求出该树的节点个数。

示例 1:

  • 输入:root = [1,2,3,4,5,6]
  • 输出:6

示例 2:

  • 输入:root = []
  • 输出:0

示例 3:

  • 输入:root = [1]
  • 输出:1

提示:

  • 树中节点的数目范围是[0, 5 * 10^4]
  • 0 <= Node.val <= 5 * 10^4
  • 题目数据保证输入的树是 完全二叉树

思路

这道就是求节点数,可以按照普通的二叉树来求,递归和层次都可以,也可以根据二叉树的性质来求: 在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1)  个节点。

大家要自己看完全二叉树的定义,很多同学对完全二叉树其实不是真正的懂了。

我来举一个典型的例子如题:

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

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

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

完全二叉树(一)如图: 222.完全二叉树的节点个数

完全二叉树(二)如图: 222.完全二叉树的节点个数1

可以看出如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉树)的节点数量。

这里关键在于如果去判断一个左子树或者右子树是不是满二叉树呢?

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

在完全二叉树中,如果递归向左遍历的深度不等于递归向右遍历的深度,则说明不是满二叉树,如图:

哪有录友说了,这种情况,递归向左遍历的深度等于递归向右遍历的深度,但也不是满二叉树,如题:

如果这么想,大家就是对 完全二叉树理解有误区了,以上这棵二叉树,它根本就不是一个完全二叉树

代码

public int countNodes(TreeNode root) {
    if (root == null) {
        return 0;
    }
    //先判断这个节点是不是满二叉树的节点
    int leftCount =1;
    int rightCount =1;
    TreeNode left = root.left;
    TreeNode right = root.right;
    while (left != null) {
        left= left.left;
        leftCount++;

    }
    while (right != null) {
        right= right.right;
        rightCount++;

    }
    //是满二叉树的节点按公式返回当前节点数为:2的深度次方-1
    if (leftCount == rightCount) {
        return (int) (Math.pow(2,rightCount)-1);
    }
    //不是满二叉树递归遍历
    int i = countNodes(root.left);
    int j = countNodes(root.right);
    return i+j+1;
}

结束

今天的递归写的很爽。