前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >判断是不是平衡二叉树

判断是不是平衡二叉树

作者头像
秦怀杂货店
发布2022-02-17 08:36:40
9600
发布2022-02-17 08:36:40
举报
文章被收录于专栏:技术杂货店技术杂货店

Part0前言

剑指Offer & LeetCode刷题仓库https://github.com/Damaer/CodeSolution 文档地址https://damaer.github.io/CodeSolution/ 刷题仓库介绍刷题仓库:CodeSolution 编程知识库https://github.com/Damaer/Coding 文档地址https://damaer.github.io/Coding/#/ 剑指OfferV1 系列已经完成,补增 V2 题目以及C++语言解法,欢迎关注~

倘若需要了解数据结构,可以点击:万字长文带你漫游数据结构世界

Part179.判断是不是平衡二叉树

1题目描述

输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树 平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

样例解释:

样例二叉树如图,为一颗平衡二叉树

注:我们约定空树是平衡二叉树。

  • 输入描述:输入一棵二叉树的根节点
  • 返回值描述:输出一个布尔类型的值

示例 1

代码语言:javascript
复制
输入: {1,2,3,4,5,6,7}

输出: true

示例 2

代码语言:javascript
复制
输入: {}

输出: true

2思路 & 解答

平衡树意味着我们需要对比任何在同一个根下的左右子树的高度差,还记得之前我们计算树的高度么,使用递归方式来解决,其实这道题与算高度差不多,只是两边高度需要算出一个差值。

算法的主要思想:

  • 不断对比每两个节点的左右子树的最大高度差,注意取差的绝对值,需要小于等于1
  • 对比完左右子树之后,需要递归左子树以及右子树进行分别判断,都满足才是平衡树

Java 代码如下:

代码语言:javascript
复制
public class Solution79 {
    public boolean IsBalanced_Solution(TreeNode root) {
        if (root == null) return true;
        // 当前左右子树是否平衡以及左右子树分别是否平衡
        return Math.abs(depth(root.left) - depth(root.right)) <= 1 && IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
    }

    private int depth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 递归获取深度
        return Math.max(depth(root.left), depth(root.right)) + 1;
    }
}

C++ 代码如下:

代码语言:javascript
复制
class Solution {
public:
    bool IsBalanced_Solution(TreeNode* root) {
        if (root == NULL) return true;
        // 当前左右子树是否平衡以及左右子树分别是否平衡
        return abs(depth(root->left) - depth(root->right)) <= 1
               && IsBalanced_Solution(root->left) && IsBalanced_Solution(root->right);
    }

    int depth(TreeNode* root) {
        if (root == NULL) {
            return 0;
        }
        // 递归获取深度
        return max(depth(root->left), depth(root->right)) + 1;
    }
};
  • 时间复杂度 O(nlogn):最差情况下,需要遍历树所有节点判断是否平衡,需要O(n)。但是判断每个节点最大高度需要递归左右子树,需要占用 O(log2n),所以总共占用O(Nlog2n)
  • 空间复杂度O(n):最差情况下,也就是树退化为链表时,递归需要使用 O(n) 的栈空间,严格意义上递归栈也需要空间。

但是上面的计算,仔细观察就会发现会有很多重复计算的过程,比如下面的数,计算子树深度的时候,计算 1 的左子树,和计算 2 的,基本都重复了。

应该如何避免这种重复计算呢?前面的是自顶向下的方式,因为每个节点都得把子树计算一遍才需要重复,如果我们从下往上计算,那不就避免了重复计算,对比逻辑如下:

  • 如果当前节点为空,高度为0
  • 如果当前节点的左子树的高度为-1,那么说明不平衡,否则,需要计算右子树高度,同样需要不等于-1,如果两者的差不符合小于等于1,那么说明它们不平衡,返回-1。通过这样 -1 异常值就会一路返回,到最初的调用处,得到不平衡的结果。

Java 代码如下:

代码语言:javascript
复制
public class Solution79 {
    public boolean IsBalanced_Solution(TreeNode root) {
        // 空树
        if (root == null) {
            return true;
        }
        return getHeight(root) != -1;
    }

    public int getHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 左子树的高度
        int left = getHeight(root.left);
        if (left < 0) {
            return -1;
        }
        // 右子树的高度
        int right = getHeight(root.right);
        if (right < 0) {
            return -1;
        }
        return Math.abs(left - right) > 1 ? -1 : 1 + Math.max(left, right);
    }
}

C++ 代码如下:

代码语言:javascript
复制
class Solution {
public:
    bool IsBalanced_Solution(TreeNode* root) {
        // 空树
        if (root == NULL) {
            return true;
        }
        return getHeight(root) != -1;
    }

    int getHeight(TreeNode* root) {
        if (root == NULL) {
            return 0;
        }
        // 左子树的高度
        int left = getHeight(root->left);
        if (left < 0) {
            return -1;
        }
        // 右子树的高度
        int right = getHeight(root->right);
        if (right < 0) {
            return -1;
        }
        return abs(left - right) > 1 ? -1 : 1 + max(left, right);
    }
};
  • 时间复杂度O(n):每个节点计算一次
  • 空间复杂度O(n):递归需要使用额外堆栈空间

【作者简介】

秦怀,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人网站:http://aphysia.cn ,关注我,我们一起成长吧~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秦怀杂货店 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Part0前言
  • Part179.判断是不是平衡二叉树
    • 1题目描述
      • 2思路 & 解答
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档