博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
剑指offer(41):判断二叉树是否为平衡二叉树(AVL树)
阅读量:4287 次
发布时间:2019-05-27

本文共 2636 字,大约阅读时间需要 8 分钟。

题目描述

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

分析

平衡二叉树(Balanced Binary Tree)又被称为AVL树,且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

直接思路:由于可以方便地递归计算二叉树的深度(参见文章)。按照AVL树的定义,顺序遍历二叉树的每一个节点,分别计算左右子树的深度,判断深度是否相差1;如果不是,直接返回false,否则递归判断该节点的左子节点和右子节点。但是该算法有一个问题,从上往下递归遍历计算每一个节点的深度时,有很多节点会发生重复遍历,越深层次的重复遍历次数越高,因此会影响性能。

代码:

public boolean IsBalanced_Solution(TreeNode root) {        if(root == null)            return true;        int leftDepth = TreeDepth(root.left);        int rightDepth = TreeDepth(root.right);        int diffDepth = leftDepth - rightDepth;        if(diffDepth < -1 || diffDepth > 1)            return false;        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);    }    public int TreeDepth(TreeNode root) {        if(root == null)            return 0;        else             return max(TreeDepth(root.left), TreeDepth(root.right)) + 1;    }    public int max(int num1, int num2) {        return (num1 > num2) ? num1 : num2;    }

推荐解法

后序遍历,左右根,判断每个节点是否是平衡节点。当遍历到一个根节点时,先遍历该根节点的左右子树,计算左右子树的深度并通过传址的方式进行向上传递;如果该根节点是平衡节点,则向上遍历该节点的父亲节点,父亲节点的深度在之前传递的深度基础上加1即可,因此避免了深度计算中的节点重复遍历,提高了效率。

后序遍历适用于对二叉树进行“自底向上”的操作。

牛客AC:

package com.problem;/** * 输入一棵二叉树,判断该二叉树是否是平衡二叉树。 *  * key: 后续遍历的方法,避免重复遍历节点 *  *  * @author Administrator * */public class BalancedBinaryTree {
class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } public boolean IsBalanced_Solution(TreeNode root) { int[] depth = {
0}; return isBalancedTree(root, depth); } /** * * @param root 根节点 * @param depth 深度,数组传址参数,需要在函数调用后改变depth,参与运算 * 类似于c++中的引用参数 * @return */ public boolean isBalancedTree(TreeNode root, int[] depth) { if(root == null) { depth[0] = 0; return true; } // 数组传址参数,用于传递函数调用后的数据,参与运算 int[] leftDepth = {
0}; int[] rightDepth = {
0}; // 后续遍历,左右根,判断每个节点是否是平衡节点 // 当遍历到一个根节点时,先遍历该根节点的左右子树,计算左右子树的深度并通过 // 传址的方式进行向上传递;如果该根节点是平衡节点,则向上遍历该节点的父亲节点, // 父亲节点的深度在之前传递的深度基础上加1即可, // 因此避免了深度计算中的节点重复遍历,提高了效率 if(isBalancedTree(root.left, leftDepth) && isBalancedTree(root.right, rightDepth)) { int diffDepth = leftDepth[0] - rightDepth[0]; if(diffDepth >= - 1 && diffDepth <= 1) { int tmpDepth = (leftDepth[0] > rightDepth[0]) ? leftDepth[0] : rightDepth[0]; depth[0] = 1 + tmpDepth; return true; } } return false; }}

参考

1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社

转载地址:http://ozxgi.baihongyu.com/

你可能感兴趣的文章
Javascript (六)高级之ECMAScript
查看>>
iOS之UISCrollView--原理
查看>>
iOS之UITableView(二)系统自带的刷新UIrefreshControl
查看>>
iOS之UICololor的使用
查看>>
iOS实现APP支持SpotLight搜索
查看>>
iOS TableView之(六)改变系统cell的image
查看>>
iOS之Tableview重用原理、重用出现的错乱三种解决方法、tablevew优化
查看>>
iOS之nil、NULL、NSNULL/Nil的区别
查看>>
iOS之alpay首页
查看>>
iOS之导航渐变---/导航透明/隐藏导航栏以及手势返回遇到的问题,状态栏颜色和背景颜色,tabbarItem角标、导航背景颜色
查看>>
iOS 新特性引导页设计
查看>>
iOS 之微信支付和支付宝合集(二)
查看>>
ios之aAPPstore信息填写、ABM申请流程
查看>>
PHP之SQL注入
查看>>
iOS之a按钮重复点击的问题、cell重复点击的问题、cell上按钮点击无效的问题
查看>>
PHP之PDO操作mysql数据库
查看>>
iOS之长按识别二维码/生成二维码/扫描二维码
查看>>
ISO之3DTouch
查看>>
iOS之指纹解锁
查看>>
iOS之healthKit
查看>>