day16 二叉树(最大、最小深度,完全二叉树的节点个数)

深度与高度

  • 深度是到根节点的距离。求解应该自顶向下,用前序遍历
  • 高度是到叶子节点的距离。求解应该自底向上,用后序遍历
  • 根节点的高度 等价于 二叉树的最大深度

104.二叉树的最大深度

深度遍历一:遍历的思想 + 回溯

遍历二叉树,同时使用额外的变量来维护结果

class Solution {
    int max = 0;
    int depth = 0;
    public int maxDepth(TreeNode root) {
        traverse(root);
        return max;
    }

    public void traverse(TreeNode root){
        if(root == null)    return ;
        depth++;
        if(root.left == null && root.right == null) max = depth > max  ? depth: max;   //叶子节点
        traverse(root.left);
        traverse(root.right);
        depth--;
    }
}

深度遍历二:子问题的思想 + 递推表达式

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null)    return 0;
        return 1 + Math.max(maxDepth(root.left),maxDepth(root.right));
    }
}

层次遍历,迭代解法

class Solution {
    public int maxDepth(TreeNode root) {
        Deque<TreeNode> que = new ArrayDeque<>();
        if(root!=null)  que.offerFirst(root);
        int max = 0;
        while(!que.isEmpty()){
            int size = que.size();
            while(size-->0){
                TreeNode cur = que.pollLast();  
                if(cur.left!=null)  que.offerFirst(cur.left);
                if(cur.right!=null)  que.offerFirst(cur.right);              
            }
            max++;
        }
        return max;
    }

}

559. N 叉树的最大深度

//深度遍历一:遍历的思想 + 回溯
class Solution {
    int max = 0;
    int depth = 0;
    public int maxDepth(Node root) {
        traverse(root);
        return max;
    }
    public void traverse(Node root){
        if(root == null)    return ;
        depth++;
        if(root.children.size() == 0) max = Math.max(depth,max);  //叶子节点
        for(Node child: root.children){
            traverse(child);
            depth--;
        }
    }
}
//深度遍历二:子问题的思想 + 递推表达式
class Solution {
    public int maxDepth(Node root) {
        if(root == null)    return 0;
        int max = 0;
        for(Node child: root.children){
            max = Math.max(maxDepth(child),max);
        }
        return max + 1;
    }
}
//层次遍历
class Solution {
    public int maxDepth(Node root) {
        Deque<Node> que = new ArrayDeque<>();
        if(root != null)    que.offerFirst(root);
        int max = 0;
        while(!que.isEmpty()){
            int size = que.size();
            while(size -- > 0){
                Node cur = que.pollLast();
                for(Node child: cur.children)   que.offerFirst(child);
            }
            max++;
        }
        return max;
    }
}

111.二叉树的最小深度

//深度遍历一:遍历的思想 + 回溯
class Solution {
    int depth = 0;
    int min = 100010;
    public int minDepth(TreeNode root) {
        if(root == null)    return 0;
        traverse(root);
        return min;
    }
    public void traverse(TreeNode root){
        if(root == null)    return;
        depth++;
        if(root.left == null && root.right == null) min = depth < min ? depth : min;
        traverse(root.left);
        traverse(root.right);
        depth--;
    }
}
//深度遍历二:子问题的思想 + 递推表达式
class Solution {
    public int minDepth(TreeNode root) {
        if(root == null)    return 0;
        int leftmin = minDepth(root.left);
        int rightmin = minDepth(root.right);
        //特殊情况,一方子树为空,另一方不为空
        if( root.left == null && root.right != null)    return rightmin + 1;  
        if( root.right == null && root.left != null)    return leftmin + 1;
        return Math.min(leftmin,rightmin) + 1;
    }
}
//层次遍历
class Solution {
    public int minDepth(TreeNode root) {
        Deque<TreeNode> que = new ArrayDeque<>();
        if(root == null)    return 0;
        que.offerFirst(root);
        int depth = 0;
        while(!que.isEmpty()){
            int size = que.size();
            depth++;
            while(size-- > 0){
                TreeNode cur = que.pollLast();
                if(cur.left == null && cur.right == null)   return depth;  //从上往下遍历,第一个叶子节点就是最小深度
                if(cur.left!=null)  que.offerFirst(cur.left);
                if(cur.right!=null) que.offerFirst(cur.right);
            }
        }
        return depth;
    }
}

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

普通二叉树解法

//深度遍历,子问题的解法
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null)    return 0;
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
//深度遍历,遍历的解法
class Solution {
    int res;
    public int countNodes(TreeNode root) {
        if(root == null)    return 0;
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
    public void traverse(TreeNode root){
        if(root == null)    return ;
        if(root != null)    res++;
        traverse(root.left);
        traverse(root.right);
    }
}
//层次遍历
class Solution {
    public int countNodes(TreeNode root) {

        if(root == null)    return 0;
        Deque<TreeNode> que = new ArrayDeque<>();
        que.offerFirst(root);
        int res = 0;
        while(!que.isEmpty()){
            TreeNode cur = que.pollLast();
            res++;
            if(cur.left!=null)  que.offerFirst(cur.left);
            if(cur.right!=null) que.offerFirst(cur.right);
        }
        return res;
    }
}

利用完全二叉树的性质

完全二叉树两种情况:

  1. 满二叉树,用公式 2 n − 1 2^n-1 2n1计算,n为树的高度;
  2. 最后一层叶子不满。这种情况则分布递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1进行计算。

判断一个树是否为满二叉树:利用满二叉树的性质,递归向左遍历的深度等于递归向右遍历的深度。

//后序遍历
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null)    return 0;   // 节点为空返回
        TreeNode l = root.left;
        TreeNode r = root.right;
        int llen = 0;
        int rlen = 0;
        while(l != null){
            llen++;
            l = l.left;
        }
        while(r != null){
            rlen++;
            r = r.right;
        }
        //当前树为完全二叉树则利用公式直接计算
        if(llen == rlen)    return (2 << llen) - 1;
        return 1 + countNodes(root.left) + countNodes(root.right);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值