二叉树13:平衡二叉树

来源:互联网 发布:动物大百科软件下载 编辑:程序博客网 时间:2024/06/05 02:26

题目:输入一棵二叉树,判断该二叉树是否是平衡二叉树。

思路:所谓平衡二叉树是指空树或者任意结点的2棵子树的高度差不差过1的树。要判断以root为根的树是否是一棵平衡二叉树,需要先判断以root.left为根的子树和以root.right为根的子树是否是平衡二叉树,如果有某一棵子树不是平衡二叉树那么整棵二叉树root就不是平衡二叉树,如果2棵子树都是平衡的,那么求2棵子树的高度的差值是否>1,如果大于1就是不平衡,否则就是平衡的。即要求root树需要先求其left和right子树,因此显然应该是对二叉树的后序遍历递归进行改造即可。

设计一个递归函数时需要考虑每次这个函数执行时需要输入什么信息,于是上一次调用时就需要收集什么信息,收集的信息可以如果只有一个,那么可以随着return进行传递,如果有多个信息,那么可以放入到数组中进行传递,或者将这些变量做成成员变量,此时不需要显式地传递,上一次递归调用对变量产生的影响会会自动在当前递归执行时产生影响。

设计一个递归函数,输入一个根结点root,判断这棵树是否是平衡二叉树,由于每次调用递归需要使用2个信息,一个是上一棵子树是否平衡true/false,另一个是上一棵子树的长度length,由于需要收集2个值,因此不能直接return。解决方法:①显然可以特殊的,当子树不是平衡二叉树时返回-1,否则是平衡二叉树就返回树的高度,这样就只要返回一个int类型的值就可以了;②设置一个递归方法所在类的成员变量flag,用来标识一棵树是否是平衡的,在递归方法中,如果处理后发现新的树不是平衡的,就将flag设置为false,否则就设置为true,当递归方法执行时,先对子树进行平衡判断,就检查这个变量即可,如果是true就是平衡的,否则就是不平衡的。这2种方法都可以,练习时使用第二种方法。其实也可以没有返回值,将树的高度height也设置为成员变量,这并不会受到递归的影响。

//判断一棵树是否是平衡二叉树,使用后序遍历的递归实现即可public class Solution {    //设置一个成员变量给递归时的各个栈帧共享    boolean flag;    int height;    public boolean IsBalanced_Solution(TreeNode root) {        //特殊输入:空子树是平衡的        if(root==null) return true;        //调用递归方法解决问题        this.process(root);        //返回结果        return flag;    }        //递归方法,判断一棵二叉树是否是平衡的,将结果设置给falg变量并返回这棵树的高度(深度,长度)    private void process(TreeNode root){        //边界条件,空节点的高度为0,flag=true        if(root==null){            flag=true;            height=0;            return;//1        }                //①先处理左子树        this.process(root.left);        int leftHeight=height;        if(!flag){            //不平衡            flag=false;            return;        }        //②处理右子树        this.process(root.right);        int rightHeight=height;// 2        if(!flag){            //不平衡            flag=false;            return;        }        //左右子树平衡://注意,由于height是所有方法共享的,因此在每次方法调用后要及时将其取出,否则在下一个方法调用时会将其覆盖        if((Math.abs(leftHeight-rightHeight))>1){            flag=false;            return;        }else{            //高度差小于等于1,平衡            flag=true;//注意:只有当前树是平衡时才需要返回新的高度,否则直接将falg设置为false,不需要设置新的高度            height=Math.max(leftHeight,rightHeight)+1;        }    }}

F1:注意:递归方法一定要有边界条件,所谓边界条件就是指出递归方法合适return,因此边界条件的处理就是将其return,可以有返回值也可以没有返回值。

F2:在递归中,不同层次的递归调用之间的参数传递可以通过类的成员变量或者全局变量来实现,每次调用递归方法就认为对成员变量height,flag进行了赋值,于是在递归方法中可以直接使用这些变量,这些变量是被递归方法处理过后的值,但是千万注意,如果有2个递归调用方法,如上面的递归1:this.process(root.left);和递归2:this.process(root.right);那么当递归1执行后就认为这个递归函数完全执行完成了,不要将其展开来理解,于是此时的flag,height是递归1处理过后的值,但是当执行递归2后,flag和height就被新的值覆盖了,而此时需要在递归1和递归2执行结束后使用2个height进行比较,显然只存在了最后覆盖的那个值,因此必须在每次递归调用后,下一次递归调用之前将全局变量赋值给定义的局部变量进行保持,这样就算全局变量被覆盖了,也不要紧。
0 0
原创粉丝点击