代码随想录:二叉树11-12

目录

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

题目

代码(层序迭代)

代码(后序递归)

代码(满二次树递归)

总结

110.平衡二叉树

题目

代码(后序递归)

代码(层序迭代)

代码(前序迭代)

总结


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

题目

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

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

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

代码(层序迭代)

class Solution {
    public int countNodes(TreeNode root) {

        //用层序迭代递归计算
        int size = 0; //初始大小为0
        Queue<TreeNode> que = new ArrayDeque<>();

        if(root == null){
            return 0;
        }

        que.offer(root);

        while(!que.isEmpty()){
            int len = que.size();  //获取当前层的节点个数
            size += len;  //更新size
            //当前层节点一个个出队
            while(len-- > 0){
                TreeNode cur = que.poll();
                //处理左右孩子,进队
                if(cur.left != null){
                    que.offer(cur.left);
                }
                if(cur.right != null){
                    que.offer(cur.right);
                }
            }
        }
        return size;
        

    }
}

代码(后序递归)

class Solution {
    public int countNodes(TreeNode root) {
        //用后序递归遍历计算
        //终止条件
        if(root == null){
            return 0;
        }
        //单层逻辑
        int left = countNodes(root.left); //计算左子树节点数量(左)
        int right = countNodes(root.right); //计算右子树节点数量(右)
        int result = left + right + 1; //中
        return result;

    }
}

代码(满二次树递归最难理解)

class Solution {
    //用完全二叉树的性质递归计算,时间复杂度小于o(n)
    //核心原理是如果是满二叉树,左右侧深度一样,可以2^depth-1直接计算,不用全部遍历
    public int countNodes(TreeNode root) {
        //终止条件1
        if(root == null){
            return 0;
        }
        //终止条件2,是满二叉树,可以直接根据深度计算节点数
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftdepth = 1;
        int rightdepth = 1;
        //左孩子一直往左下走,计算左下深度
        while(left != null){
            left = left.left;
            leftdepth++;
        }
        //右孩子一直往右下走,计算右下深度
        while(right != null){
            right = right.right;
            rightdepth++;
        }
        //如果左右深度一样,说明是满二叉树,直接计算返回
        if(leftdepth == rightdepth){
            return ((int)Math.pow(2,leftdepth) - 1);
        }

        //单层逻辑
        int l = countNodes(root.left); //计算左孩子节点数(左)
        int r = countNodes(root.right); //计算右孩子节点数(右)
        int result = l + r + 1; //中
        return result;
    }
}

总结

        层序迭代和后序递归的核心逻辑很简单,就是用普通的遍历二叉树的方法,一边遍历一边计算节点数,即在原先的遍历代码中加上计算节点数的代码即可。时间复杂度是o(n)。

        满二叉树递归的核心逻辑,利用了满二叉树的性质,如果一个子树的满二叉树,从根节点往左和往右的最大深度是一样的。因此我们通过前序递归遍历二叉树,如果当前节点时满二叉树(终止条件),就可以直接计算节点数是2^depth-1,不用继续遍历其孩子节点。如果不是满二叉树(单层逻辑),就继续前序遍历下去,不是满二叉树的节点数=左子树节点+右子树节点+1。时间复杂度<=o(n)。

110.平衡二叉树

题目

给定一个二叉树,判断它是否是平衡二叉树

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

代码(后序递归最难理解)

class Solution {
    //后序递归判断
    public boolean isBalanced(TreeNode root) {
        int result = postOrder(root);
        if(result == -1){
            return false;
        }
        else{
            return true;
        }

    }
    //后序遍历,判断每个节点是否满足高度差<=1
    //返回值int有两层意思:如果=-1代表当前节点不平衡,如果不是-1,代表当前节点的高度
    public int postOrder(TreeNode root){
        //终止条件1
        if(root == null){
            return 0;
        }
        //计算当前节点的左右孩子高度
        int leftheight = postOrder(root.left); //左子树高度
        int rightheight = postOrder(root.right); //右子树高度
        //终止条件2,左子树不平衡
        if(leftheight == -1){
            return -1;
        }
        //终止条件3,右子树不平衡
        if(rightheight == -1){
            return -1;
        }
        //终止条件4,左右子树高度差大于1
        if(Math.abs(leftheight - rightheight) > 1){
            return -1;
        }
        //单层循环
        //如果该节点满足平衡二叉条件,计算该节点的高度,继续递归判断
        int result = 1 + Math.max(leftheight,rightheight);
        return result;

    }
}

代码(层序迭代)

class Solution {
    //层序迭代判断,核心逻辑是层序遍历每个节点,判断是否满足平衡条件
    public boolean isBalanced(TreeNode root) {
        //层序遍历节点,逐个判断该节点是否满足高度差<=1
        Queue<TreeNode> que = new ArrayDeque<>();

        if(root == null){
            return true;
        }

        que.offer(root);

        while(!que.isEmpty()){
            int size = que.size();
            //处理当前层的所有节点
            while(size-- > 0){
                TreeNode cur = que.poll();
                //计算cur的左右孩子的高度
                int leftheight = getheight(cur.left);
                int rightheight = getheight(cur.right);
                //如果高度差>1,不满足平衡直接return
                if(Math.abs(leftheight - rightheight) > 1){
                    return false;
                }
                if(cur.left != null){
                    que.offer(cur.left);
                }
                if(cur.right != null){
                    que.offer(cur.right);
                }
            }
        }
        return true;
    }
    //计算cur节点的高度
    public int getheight(TreeNode cur){
        //终止条件
        if(cur == null){
            return 0;
        }
        //单层逻辑
        int left = getheight(cur.left);
        int right = getheight(cur.right);
        return 1 + Math.max(left,right);
    }
}

代码(前序迭代)

class Solution {
    
    public boolean isBalanced(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        if(root == null){
            return true;
        }
        //前序迭代遍历每一个节点,并判断该节点是否平衡
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode cur = stack.pop();
            //计算当前cur节点的左右高度
            int leftheight = getheight(cur.left);
            int rightheight = getheight(cur.right);
            //如果cur不平衡,直接返回false
            if(Math.abs(leftheight - rightheight) > 1){
                return false;
            }
            if(cur.right != null){
                stack.push(cur.right);
            }
            if(cur.left != null){
                stack.push(cur.left);
            }
        }
        //遍历完全部节点,都满足平衡,就返回true
        return true;
        
    }
    
    //计算cur节点的高度
    public int getheight(TreeNode cur){
        //终止条件
        if(cur == null){
            return 0;
        }
        //单层逻辑
        int left = getheight(cur.left);
        int right = getheight(cur.right);
        return 1 + Math.max(left,right);
    }
}

总结

        迭代法的逻辑很简单,就是用前序、层序遍历每一个节点时,同时计算当前节点的左右孩子高度,判断当前节点的高度差是否满足平衡,如果不满足,直接返回false,如果当前节点满足,再迭代判断后面的节点。最后,如果所有节点遍历完,都没有返回false,说明二叉树的每一个节点都满足平衡条件,就返回true。

        递归法,核心逻辑是一边后序递归二叉树,一边计算当前节点的左右孩子高度,判断当前遍历节点是否满足平衡,如果不满足平衡就返回-1,如果满足平衡就计算当前节点的高度。

         递归法有四个终止条件,一是节点为null,返回0。二是节点的左右高度差>1,返回-1。还有两种情况千万不能漏,如果该节点的左孩子or右孩子的返回值=-1,说明其左孩子or右孩子已经不平衡了,直接返回-1。

  • 29
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

守岁白驹hh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值