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

104. 二叉树的最大深度

什么是深度,什么是高度,如何求深度,如何求高度,这里有关系到二叉树的遍历方式。

大家要先看视频讲解,就知道以上我说的内容了,很多录友刷过这道题,但理解的还不够。

题目链接/文章讲解/视频讲解: 代码随想录

重点:

1. 深度是从根节点开始算,高度是从叶子节点开始算

2. 深度用前序遍历求,高度用后序遍历求

3. 本题虽然为深度,但根节点的最大深度其实就是他的高度,所以用后序遍历求

思路:

递归法:

1. 递归的求左孩子的高度和右孩子的高度,取一个最大值加1即为根节点的高度

迭代法:

1. 用队列把存入当前层的元素,size记录当前层还剩几个节点没有遍历,遍历完一层result就++

// 递归,后序遍历
public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 左
        int leftChildDepth = maxDepth(root.left);
        // 右
        int rightChildDepth = maxDepth(root.right);
        // 中
        return 1 + Math.max(leftChildDepth, rightChildDepth);
}
// 迭代法,层序遍历
public int maxDepth(TreeNode root) {
        int result = 0;
        if (root == null) {
            return result;
        }
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offerLast(root);
        while (!queue.isEmpty()) {
            // 当前这一层有几个几点
            int size = queue.size();
            // 循环遍历完这一层
            while (size > 0) {
                TreeNode cur = queue.removeFirst();
                if (cur.left != null) {
                    queue.offerLast(cur.left);
                }
                if (cur.right != null) {
                    queue.offerLast(cur.right);
                }
                size--;
            }
            // 遍历完一层说明深度加一
            result++;
        }
        return result;
}

559. N叉树的最大深度

题目链接/文章讲解/视频讲解: 代码随想录

思路:

递归法:

1. 把children们递归的求深度,返回给根节点时加一即可

迭代法:

1. 用队列进行层序遍历,size记录当前层还剩几个节点没有遍历完,遍历完一层result加一

// 递归法,后序遍历
public static int maxDepth(Node root) {
        if (root == null) {
            return 0;
        }
        int childDepth = 0;
        if (root.children != null) {
            // 求子树的高度
            for (Node child : root.children) {
                int tmp = maxDepth(child);
                childDepth = Math.max(tmp, childDepth);
            }
        }
        // 中
        return 1 + childDepth;
}
// 迭代法,层序遍历
public static int maxDepth(Node root) {
        if (root == null) {
            return 0;
        }
        int result = 0;
        Deque<Node> queue = new LinkedList<>();
        queue.offerLast(root);
        while (!queue.isEmpty()) {
            // 当前层有几个节点
            int size = queue.size();
            // 遍历当前层所有节点
            while (size > 0) {
                Node cur = queue.removeFirst();
                // 有孩子就加入队列
                if (cur.children != null) {
                    for (Node child : cur.children) {
                        queue.offerLast(child);
                    }
                }
                size--;
            }
            // 一层遍历完,result加一
            result++;
        }
        return result;
}

111. 二叉树的最小深度(优先掌握递归)

先看视频讲解,和最大深度看似差不多,其实 差距还挺大,有坑。

题目链接/文章讲解/视频讲解:代码随想录

思路:

递归法:

1. 递归的求左右孩子的高度,并取最小,但当左子树为空时,我们用右子树的最小高度,当右子树为空时,我们用左子树的最小高度

迭代法:

1. 用队列一层一层遍历,size记录当前层还剩余几个节点没遍历,遇到叶子节点直接返回结果

// 递归,后序遍历
public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 左
        int leftChildDepth = minDepth(root.left);
        // 右
        int rightChildDepth = minDepth(root.right);
        // 中
        // 左子树为空时,取右子树
        if (root.left == null) {
            return 1 + rightChildDepth;
        }
        // 右子树为空时,取左子树
        if (root.right == null) {
            return 1 + leftChildDepth;
        }
        // 左右都不为空,取最小值
        return 1 + Math.min(leftChildDepth, rightChildDepth);
}
// 迭代法,层序遍历
public int minDepth(TreeNode root) {
        int result = 0;
        if (root == null) {
            return result;
        }
        Deque<TreeNode> queue = new LinkedList<>();
        queue.offerLast(root);
        while (!queue.isEmpty()) {
            // 当前这一层有几个几点
            int size = queue.size();
            result++;
            // 循环遍历完这一层
            while (size > 0) {
                TreeNode cur = queue.removeFirst();
                // 遇到叶子节点了,直接返回结果
                if (cur.left == null && cur.right == null) {
                    return result;
                }
                if (cur.left != null) {
                    queue.offerLast(cur.left);
                }
                if (cur.right != null) {
                    queue.offerLast(cur.right);
                }
                size--;
            }
        }
        return result;
}

222. 完全二叉树的节点个数(优先掌握递归)

需要了解,普通二叉树 怎么求,完全二叉树又怎么求

题目链接/文章讲解/视频讲解:代码随想录

思路:

1. 按照普通二叉树来求解:

递归的求左右孩子的个数,然后相加再加一即可

2. 按照完全二叉树的特性来求解:

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

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

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

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

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

利用完全二叉树中肯定存在满二叉树的特性可以帮助我们不去遍历满二叉树的外侧节点。

// 当作普通二叉树处理,后序遍历
public static int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 左
        int leftCount = countNodes(root.left);
        // 右
        int rightCount = countNodes(root.right);
        // 中
        return 1 + leftCount + rightCount;
}
// 利用完全二叉树的特性,完全二叉树里面肯定存在满二叉树
// 所以我们的终止条件就可以加多一个满二叉树的判断
public static int countNodes(TreeNode root) {
        // 第一个终止条件
        if (root == null) {
            return 0;
        }
        // 第二个终止条件
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftDepth = 0;
        int rightDepth = 0;
        while (left != null) {
            left = left.left;
            leftDepth++;
        }
        while (right != null) {
            right = right.right;
            rightDepth++;
        }
        // 发现了子树为满二叉树,直接用公式计算
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1;
        }
        // 单层递归逻辑
        // 左
        int leftChildDepth = countNodes(root.left);
        // 右
        int rightChildDepth = countNodes(root.right);
        // 中
        return 1 + leftChildDepth + rightChildDepth;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值