《剑指offer》-平衡二叉树

本文介绍两种判断二叉树是否平衡的方法:一种是通过计算每个节点左右子树的深度并比较;另一种是在递归过程中同时计算节点深度,避免重复计算,降低复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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


解法:

一、常规理解法(复杂度高o(N^2))

1.计算出每个需要遍历结点左右子树的深度,然后将左右子树的深度作差,若绝对值大于1,则非平衡二叉树,否则即为平衡二叉树

2.不足之处就是,当前节点计算时,需要遍历其左子树的所有节点,那么在将左子树的节点作为节点时候,又需要遍历它下面的所有节点,这样会造成计算复杂度偏高

3.不过这种方法易于理解,能够记得住

class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
		if(pRoot == NULL) return true;
        int left = TreeDepth(pRoot->left);  //计算出每个节点的深度
        int right = TreeDepth(pRoot->right); //计算出每个节点的深度
        int diff = left - right;  //深度作差
        if(diff > 1 || diff < -1) return false;
        return IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->right);
    }
    int TreeDepth(TreeNode* pRoot)
    {
    	if(pRoot == NULL) return 0;
        int left = TreeDepth(pRoot->left);
        int right = TreeDepth(pRoot->right);
        return (left > right) ? (left+1) : (right+1);
    }
};

二、低复杂度方法(复杂度o(n))

1.先判断左右子树是否平衡,在递归判定的同时,计算出父节点的深度

2.这个递归相当于二叉树的后续遍历,先递归到底,访问最左的子节点,然后再递归访问右节点,在递归的同时,计算出父节点的深度,那么在往上走的时候,下面的节点就不用再次遍历下面的节点计算深度了,因为递归的时候已经把父节点的深度给记录下来了,这样节省了时间

3.这种方法比较好,就是理解起来有点绕,可能是用到了后续遍历的思想,并且在递归的同时保留计算父节点的深度,用作下一次递归用,与一方法不同的是,从下往上走,先判断叶子节点,慢慢地往上走的过程,而一方法是直接从上往下判断,深度计算有重复遍历的缺点。

4.关键理解这种思想,递归确实不好理解,把它当做只有2层深度的来理解,然后慢慢往上加深度,可能做多了就会有感觉吧

class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(pRoot == NULL) return true;
        int height = 0;
        return IsBalanced(pRoot, height);
    }
    bool IsBalanced(TreeNode* pRoot, int &height) {  //注意第二个参数是引用类型,在函数递归时候每次是本身变化
		if(pRoot == NULL) return true;
        int left  = 0, right = 0;
        if(!IsBalanced(pRoot->left, left)) return false;  //先递归到底,相当于后序遍历
        if(!IsBalanced(pRoot->right, right)) return false;
        if(abs(left-right) > 1) return false;   //再判断左右子树是否平衡
        height = 1 + ((left > right) ? left:right);//到底后再计算父节点深度
        return true;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值