• 算法练习(12)-二叉树的递归套路


    如果二叉树的问题,可以分解为 先处理左树, 再处理右侧, 这种就可以用"左程云"推荐的所谓"递归套路"解法, 其代码模板大致象下面这样:

    class ReturnType{
        //定义要返回的信息
        public ... ;
    
        //构造函数
        public ReturnType(...){
    
        }
    }
    
    ReturnType process(TreeNode n){
        //退出递归的base条件
        if (n==null){
            ...
        }
    
        //向左树要信息
        ReturnType leftData = process(n.left);
        //向右树要信息
        ReturnType rightData = process(n.right);
    
        //...组装最终结果
        return new ReturnType(...);
    }
    

      
    来看几个示例: (注: 以下题目从效率上讲, 可能有更好的解法, 这里只是为了演示如何使用左神的这个递归思路)

    示例1: 求二叉树的高度和节点总数?

    思路: 整颗树的节点总数 ,等于左子树的节点数+右子树的节点数,  高度=max(左子树的高度, 右子树的高度), 所以这个问题可以分解为 不停向 左 、右子树 要 高度(height)及节点数(size)

    /**
     * 先定义左、右子树需要返回的信息体
     */
    static class ReturnType {
        public int height;
        public int size;
    
        public ReturnType(int h, int size) {
            this.height = h;
            this.size = size;
        }
    }
    
    /**
     * 再递归调用
     * @param x
     * @return
     */
    static ReturnType process(TreeNode x) {
        //退出递归的边界判断
        if (x == null) {
            return new ReturnType(0, 0);
        }
        //向左树要信息
        ReturnType leftData = process(x.left);
        //向右树要信息
        ReturnType rightData = process(x.right);
        
        //组装左树+右树的信息
        return new ReturnType(Math.max(leftData.height, rightData.height) + 1, leftData.size + rightData.size + 1);
    }
    

      

    示例2:如何判断一颗树是满二叉树?

    思路:满二叉树的特性, 最后一层叶子节点都是左右双全的, 而且左\右子树的高度相等, 如果这2个条件满足, 必然节点总数=2^k -1 , 即2的k次方,再减1( 注:k为树的高度)

    示例1中, 已经求出了节点数, 以及高度k,只要校验一下size是否等于2^height -1

     /**
         * 先定义左、右子树需要返回的信息体
         */
        static class ReturnType {
            public int height;
            public int size;
            //这个变量,不用左右子树返回,只是放在这里方便最终使用而已
            public boolean isFBT = false;
    
            public ReturnType(int h, int size) {
                this.height = h;
                this.size = size;
            }
        }
    
        /**
         * 判断是否满二叉树(Full Binary Tree)
         *
         * @param x
         * @return
         */
        static ReturnType process(TreeNode x) {
            //退出递归的边界判断
            if (x == null) {
                return new ReturnType(0, 0);
            }
            //向左树要信息
            ReturnType leftData = process(x.left);
            //向右树要信息
            ReturnType rightData = process(x.right);
    
            int height = Math.max(leftData.height, rightData.height) + 1;
            int size = leftData.size + rightData.size + 1;
    
            //组装左树+右树的信息
            ReturnType returnType = new ReturnType(height, size);
            //检查总节点数符合满2叉树特点
            returnType.isFBT = ((1 << height) - 1) == size;
            return returnType;
        }
    

      

    示例3:如何判断一颗树是平衡二叉树?

       /**
         * 先定义左、右子树需要返回的信息体
         */
        static class ReturnType {
            public int height;
            //这个变量,不用左右子树返回,只是放在这里方便最终使用而已
            public boolean isAVL = false;
    
            public ReturnType(int h) {
                this.height = h;
            }
        }
    
        /**
         * 判断是否满平衡二叉树
         *
         * @param x
         * @return
         */
        static ReturnType process(TreeNode x) {
            //退出递归的边界判断
            if (x == null) {
                return new ReturnType(0);
            }
            //向左树要信息
            ReturnType leftData = process(x.left);
            //向右树要信息
            ReturnType rightData = process(x.right);
    
            int height = Math.max(leftData.height, rightData.height) + 1;
    
    
            //组装左树+右树的信息
            ReturnType returnType = new ReturnType(height);
            returnType.isAVL = Math.abs(leftData.height - rightData.height) <= 1;
            return returnType;
        }
    

      

    示例4:如何判断一颗树是搜索二叉树?

    思路:搜索二叉树的特征, 左边的节点, 肯定比自己小, 右边的节点比自己大. (假设树中没有重复节点) ,  违反这个规则就不是搜索二叉树了, 所以可分解为不停向左右子树询问 "你是不是搜索二叉树? 你的最大节点和最小节点值是多少?" 

    static class ReturnType {
        public boolean isBst;
        public int min = Integer.MIN_VALUE;
        public int max = Integer.MAX_VALUE;
    
        public ReturnType(boolean bst, int min, int max) {
            this.isBst = bst;
            this.min = min;
            this.max = max;
        }
    }
    
    static ReturnType process(TreeNode n) {
        if (n == null) {
            return null;
        }
        ReturnType leftData = process(n.left);
        ReturnType rightData = process(n.right);
        int min = n.val;
        int max = n.val;
        if (leftData != null) {
            min = Math.min(min, leftData.min);
            max = Math.max(max, leftData.max);
        }
        if (rightData != null) {
            min = Math.min(min, rightData.min);
            max = Math.max(max, rightData.max);
        }
        boolean isBst = true;
        //左树不是搜索树, 或左树的最大节点比自己还大, 整体必然不是搜索二叉树
        if (leftData != null && (!leftData.isBst || leftData.max >= n.val)) {
            isBst = false;
        }
        //右树不是搜索树, 或右树的最小节点比自己还小, 整体必然不是搜索二叉树
        if (rightData != null && (!rightData.isBst || rightData.min <= n.val)) {
            isBst = false;
        }
        return new ReturnType(isBst, min, max);
    }
    
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    the schema version of 'microsoft.aspnet.mvc' is incompatible with version of nuget
    ODBC连接到400
    PC端使用program來CHGUSRPRF
    Could not load file or assembly 'System.Data.SQLite' or one of its dependencies. An attempt was made
    编辑器,按钮等等,图片上传到服务器的原理-----图片上传预览原理及实现
    dedecms,ajax提交,前端验证,前端提示,以及30秒后再提交
    js提交表单的时候,30秒后才能提交第二次
    z-dialog下载,以及使用教程---下载zdialog以后,有案例,那里才是官方最全的教程
    Resource interpreted as Stylesheet but transferred with MIME type application/javascript
    dedecms ajax表单提交,以及如何返回json的数据,以及数组的写法
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/15477609.html
Copyright © 2020-2023  润新知