剑指offer面试题39:二叉树深度与平衡二叉树

来源:互联网 发布:8080端口外网访问 编辑:程序博客网 时间:2024/04/29 03:12
题目一:二叉树深度
            输入一颗二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为数的深度
题目二:平衡二叉树
            输入一颗二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一颗平衡二叉树。例如,图中即为一颗平衡二叉树。
算法分析:

算法1.每个节点只遍历一次
如果我们用后续遍历的方式遍历二叉树的每一个节点,在遍历到一个节点之前我们就已经遍历了它的左右子树。只要在遍历每个节点的时候记录他的深度(某一节点的深度等于它到叶节点的长度),我们就可以一边遍历一遍判断每个节点是不是平衡的。

算法2.重复遍历
在遍历树的每个节点的时候,调用函数TreeDepth得到他的左右树的深度。如果每个节点的左右子树的深度相差都不超过1,按照定义则它就是一棵平衡二叉树。但该算法的某些节点会被重复遍历多次,时间效率不高。

遇到问题:
在算法1中,定义depth和left,right变量不能使用整型变量,而要使用只保存一个数据的一维数组,使用整形变量后,在递归调用一下语句时:
               int left = 0;                                            //不能使用变量,应该使用数组保存
               int right = 0;      
                int diff = leftright;
            System.out.println("left= " + left+",right="+right);
            if(diff <= 1 && diff >= -1){
                 depth = 1 + (left > right ? left:right);
                 System.out.println("depth=" + depth);
                return true;
            }  
就会遇到问题,每次都会将left和right的值重新赋值为0,而采用数组时,虽然有以下语句:
          int[] left = new int[1];
        int[] right = new int[1];
        if(IsBalancedHelper(root.leftNodeleft)&& IsBalancedHelper(root.rightNoderight)){
            int diff = left[0] - right[0];
            System.out.println("left[0] = " + left[0] + ",right[0]=" + right[0]);
            if(diff <= 1 && diff >= -1){
                 depth[0] = 1 + (left[0] > right[0] ? left[0]:right[0]);
                 System.out.println("depth=" + depth[0]);            //此处depth值依次为r6,r4,r5,r2,r3的深度
                return true;
            }  
但根据Java的“引用”规则,left[]和right[]数组中每次都会保存的是递归调用后depth的值,即为
left[0] = 0,right[0]=0
depth=1
left[0] = 0,right[0]=1
depth=2
left[0] = 0,right[0]=0
depth=1
left[0] = 2,right[0]=1
depth=3
left[0] = 0,right[0]=0
depth=1
left[0] = 3,right[0]=1 
 所以,在递归调用时,要注意变量的定义,防止在每次递归调用时重新刷新原有值。
生成二叉树的方法:
class TreeNode{
    int val;
    TreeNode leftNode = null;
    TreeNode rightNode = null;
    public TreeNode(int val){
        this.val = val;
    }
}
 先定义一个二叉树类,然后 使用下面方法对二叉树进行赋值。
/*    
                    1   
                   / \   
                  2   3   
                 / \     
                4   5   
                 \
                  6      
          */
            TreeNode r1 = new TreeNode(1);
            TreeNode r2 = new TreeNode(2);
            TreeNode r3 = new TreeNode(3);
            TreeNode r4 = new TreeNode(4);
            TreeNode r5 = new TreeNode(5);
            TreeNode r6 = new TreeNode(6);
            
            r1.leftNode = r2;
            r1.rightNode = r3;
            r2.leftNode = r4;
            r2.rightNode = r5;
            r4.rightNode = r6; 
 

算法源程序:

/**************************************************************      * Copyright (c) 2016, * All rights reserved.                   * 版 本 号:v1.0                   * 题目描述:平衡二叉树*        输入一颗二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,* 那么它就是一颗平衡二叉树。例如,图中即为一颗平衡二叉树。* 例如:下面二叉树打印出 1,2,3,4,5,6.*        1   *       / \   *      2   3   *     / \     *    4   5          *     \*      6* 输入描述:无* 程序输出: 见运行后结果* 问题分析: * 算法描述: 如果我们用后续遍历的方式遍历二叉树的每一个节点,在遍历到一个节点之前我们就已经遍历了它的左右子树。* 只要在遍历每个节点的时候记录他的深度(某一节点的深度等于它到叶节点的长度),我们就可以一边遍历一遍判断每个节点是不是平衡的。* 算法2.重复遍历*在遍历树的每个节点的时候,调用函数TreeDepth得到他的左右树的深度。如果每个节点的左右子树的深度相差都不超过1,*按照定义则它就是一棵平衡二叉树。但该算法的某些节点会被重复遍历多次,时间效率不高。* 完成日期:2016-09-26***************************************************************/package org.marsguo.offerproject39;//import org.marsguo.offerproject.TreeNode;class TreeNode{int val;TreeNode leftNode = null;TreeNode rightNode = null;public TreeNode(int val){this.val = val;}}/*算法1.较为复杂*/class FindBalanceTree{public static boolean isBalanced2(TreeNode root){int[] depth = new int[1];//int depth = 0;不能使用变量,应该使用数组保存return IsBalancedHelper(root,depth);}public static boolean IsBalancedHelper(TreeNode root,int[] depth){if(root == null){//depth = 0;depth[0] = 0;return true;}int[] left = new int[1];int[] right = new int[1];//System.out.println("left=" + left[0] + ",right= " + right[0]);//int left = 0;//不能使用变量,应该使用数组保存//int right = 0;if(IsBalancedHelper(root.leftNode, left)&& IsBalancedHelper(root.rightNode, right)){int diff = left[0] - right[0];//System.out.println("left[0] = " + left[0] + ",right[0]=" + right[0]);if(diff <= 1 && diff >= -1){ depth[0] = 1 + (left[0] > right[0] ? left[0]:right[0]); System.out.println("depth=" + depth[0]);//此处depth值依次为r6,r4,r5,r2,r3的深度return true;}//int diff = left- right;//System.out.println("left= " + left+",right="+right);//if(diff <= 1 && diff >= -1){// depth = 1 + (left > right ? left:right);// System.out.println("depth=" + depth);//return true;//}}return false;}}/*算法2.简单,但一个节点会重复遍历多次*/class SolutionMethod2{public boolean isBalancedSolution(TreeNode root){if(root == null)return true;int left = getDepth(root.leftNode);//此处得到的是r2的深度,不是r1;r2深度为3int right = getDepth(root.rightNode);//此处得到的是r3深度,不是r1;r3深度为1System.out.println("算法2:left= " + left + "right= " + right);System.out.println("算法2:left-right= " + (left - right));return (Math.abs(left-right) >1)? false:true;//Math.abs() 取绝对值,}public int getDepth(TreeNode root){if(root == null)return 0;int left = getDepth(root.leftNode) + 1;int right = getDepth(root.rightNode) + 1;/*此处输出的left和right值依次为:r6,r4,r5,r2,r3的深度*/System.out.println("left = " + left + ", right = " + right);return left > right? left:right;}}public class BalanceTree {public static void main(String[] args){/*        1          / \         2   3        / \         4   5        \      6        */TreeNode r1 = new TreeNode(1); TreeNode r2 = new TreeNode(2);TreeNode r3 = new TreeNode(3);TreeNode r4 = new TreeNode(4);TreeNode r5 = new TreeNode(5);TreeNode r6 = new TreeNode(6);r1.leftNode = r2;r1.rightNode = r3;r2.leftNode = r4;r2.rightNode = r5;r4.rightNode = r6;/*1   / \  2   3 / \   \4   5   6     \      7      */TreeNode r21 = new TreeNode(1);TreeNode r22 = new TreeNode(2);TreeNode r23 = new TreeNode(3);TreeNode r24 = new TreeNode(4);TreeNode r25 = new TreeNode(5);TreeNode r26 = new TreeNode(6);TreeNode r27 = new TreeNode(7);r21.leftNode = r22;r21.rightNode = r23;r22.leftNode = r24;r22.rightNode = r25;r25.rightNode = r27;r23.rightNode = r26;//FindBalanceTree findbalancetree = new FindBalanceTree();//调用静态方法,所以不用生成对象,直接采用类名调用System.out.println("采用算法1的输出:" + FindBalanceTree.isBalanced2(r1));SolutionMethod2 solution2 = new SolutionMethod2();System.out.println("采用算法2的输出:" + solution2.isBalancedSolution(r1));System.out.println("第二棵树采用算法1的输出:" + FindBalanceTree.isBalanced2(r21));SolutionMethod2 solution22 = new SolutionMethod2();System.out.println("第二棵树采用算法2的输出:" + solution22.isBalancedSolution(r21));}}

程序运行结果:


0 0
原创粉丝点击