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

本文深入探讨了LeetCode中涉及递归算法的四道题目,包括104.最大深度的二叉树、559.最大深度的N叉树、111.最小深度的二叉树以及222.完全二叉树的节点计数。通过递归和迭代方法解决这些二叉树问题,特别强调了完全二叉树特性的应用,以优化解决方案的时间复杂度。
摘要由CSDN通过智能技术生成

Leetcode题目-104. Maximum Depth of Binary Tree

链接: 104. Maximum Depth of Binary Tree

思路

这道题在层序遍历里面已经做过一次了,利用层序遍历的思路也容易理解,得到结果。这里主要讨论一下它的递归做法,同时巩固一下对递归思路的掌握。

  1. 递归函数:根据根节点求深度,public int maxDepth(TreeNode root)
  2. 递归终止条件:if (root == null) { return 0;}
  3. 单次递归逻辑:求左子树深度,求右子树深度,再加上自身深度

代码实现

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int depth = 0;
        depth = 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
        return depth;
    }
}

Leetcode题目-559. Maximum Depth of N-ary Tree

链接: 559. Maximum Depth of N-ary Tree

思路

n叉树的原理几乎同理,可以使用层序遍历的迭代法求解,只不过在处理左右子树的步骤,是遍历n叉树的所有子树。同时这里也主要讨论其递归法。

  1. 递归函数:根据根节点求深度,public int maxDepth(Node root)
  2. 递归终止条件: if (root == null) { return 0;}
  3. 单次递归逻辑:获取每一个子树的深度,去最大值,并加上自身深度

代码实现

class Solution {
    public int maxDepth(Node root) {
        if (root == null) {
            return 0;
        }

        int depth = 0;
        for (Node node : root.children) {
            depth = Math.max(depth, maxDepth(node));
        }

        return 1 + depth;
    }
}

Leetcode题目-111. Minimum Depth of Binary Tree

链接: 111. Minimum Depth of Binary Tree

思路

最小值需要注意,这里可不是把上题的求最大值换成求最小值就可以了,这里会遇到一种特殊情况,就是当节点左子树为空,右子树不为空时,此时它并不是一个叶子节点,但是取子树的最小深度会取成0,从而把它误认为是一个叶子节点。所以需要分别判断左右子树是否为空的情况。
如果使用层序遍历迭代法也可以较容易求的。

代码实现

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }

        if (root.left == null && root.right != null) {
            return minDepth(root.right) + 1;
        }
        if (root.left != null && root.right == null) {
            return minDepth(root.left) + 1;
        }

        return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
    }
}

Leetcode题目-222. Count Complete Tree Nodes

链接: 222. Count Complete Tree Nodes

思路

这里使用递归和迭代可以将此完全二叉树当作普通二叉树处理,但是这样的复杂度是O(n),且没有用到完全二叉树的特性,题目中也提出要求复杂度小于O(n)。所以我们要用到完全二叉树的特性来求解。作为一个完全二叉树,其只有可能是满二叉树或最底层叶子结点未满两种情况。对于满二叉树,其有特点,一个深度为n的满二叉树,其节点个数为2^n-1个,所以可以利用这一特性求节点数;对于最底层叶子结点未满的情况,可以分别递归其左右子树,在某一深度,总会出现满二叉树(叶子结点也算是一个深度为1的满二叉树)。这样求解的时间复杂度,为O(logn * logn)

代码实现

1. 普通二叉树递归
class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }

        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
2. 利用完全二叉树特性(写法一)
class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }

        TreeNode cur = root;
        // 这里深度是包括根节点的,从1开始算
        int leftDepth = 0;
        int rightDepth = 0;
        while (cur != null) {
            leftDepth++;
            cur = cur.left;
        }
        cur = root;
        while (cur != null) {
            rightDepth++;
            cur = cur.right;
        }

        if (leftDepth == rightDepth) {
            return (1 << leftDepth) - 1;
        }

        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
2. 利用完全二叉树特性(写法二)
class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }

        int leftDepth = getDepth(root.left);
        int rightDepth = getDepth(root.right);
        // 左右子树深度相同,则此时左子树一定被填满了,为满二叉树
        if (leftDepth == rightDepth) {
            // 左子树节点数为1<<leftDepth-1
            // 根节点节点数+1
            // 右子树继续计算(因为叶子结点也算一个满二叉树,所以最后总会遍历结束,不会存在死循环)
            return (1 << leftDepth) + countNodes(root.right);
        // 左右子树深度不相同,则左子树不一定为满二叉树(树的最后一层没满),但倒数第二层一定满了,所以右子树的一定为满二叉树
        } else {
            return (1 << rightDepth) + countNodes(root.left);
        }
    }

    private int getDepth(TreeNode root) {
        int depth = 0;
        while (root != null) {
            depth++;
            root = root.left;
        }
        return depth;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值