题目描述
实现一个函数,检查二叉树是否平衡,平衡的定义如下,对于树中的任意一个结点,其两颗子树的高度差不超过1。
给定指向树根结点的指针TreeNode* root,请返回一个bool,代表这棵树是否平衡。
题目分析:
<方法1>:
平衡二叉树是通过左右子树的高度来判断是否为平衡二叉树的,所以我们首先想到的是如何求一个树的高度,求一个树的高度很简单,递归求解,每次求出左右子树的最大高度再加1便是父节点的高度,这样递归下去,便可以求出任何一颗树的高度。
既然可以求出任何一个节点的高度,那么通过再次遍历二叉树,判断任何一个节点的左右子树高度相差是否满足平衡二叉树便可实现平衡二叉树的判断。
求一颗平衡树高度的时间复杂度为O(logN),那么在第二次遍历的时候需要求每个节点的高度时间复杂度为O(NlogN)。其实这个过程大部分都是重复判断的,下面的方法是该方法的浓缩。
<方法2>:
后序遍历的方式,保存当前求得的深度,上层的节点就是当前的深度加1,所以每个节点只求一次,效率上来了, 该方法的时间复杂度只有O(logN)
#include<iostream>
using namespace std;
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL) { }
};
//方法一:对每一个节点都求出左右子树的高度,判断出树是不是平衡,但是这种方式会多次遍历叶子节点
//效率低下。
/*
int Heigh(TreeNode *root)
{
if (root == NULL)
return 0;
int left = Heigh(root->left);
int right = Heigh(root->right);
return left > right ? left+1 : right+1;
}
bool IsBalance(TreeNode * root)
{
if(root == NULL) //空树也是一颗平衡二叉树。
return true;
//判断根节点是不是平衡。
int left = Heigh(root->left);
int right = Heigh(root->right);
if(left - right < -1 || left - right > 1)
{
return false;
}
//判断左右孩子是不是平衡
return IsBalance(root->left) && IsBalance(root->right);
}
*/
//方式二,用后序遍历的方式,每个节点只是访问一次,但是要多一个参数把高度带出来。
bool IsBalance(TreeNode *root,int& heigh)
{
if(root == NULL)
{
heigh = 0;
return true;
}
int left = 0;
int right = 0;
if( IsBalance(root->left,left) && IsBalance(root->right,right) )
{
if( (left - right <= 1) && (left - right >= -1) )
{
heigh = left> right ? left+1 :right+1;
return true;
}
}
return false;
}
bool IsBalance(TreeNode *root)
{
int heigh = 0;
return IsBalance(root,heigh) ;
}
void test()
{
TreeNode *p1 = new TreeNode(10);
TreeNode *p2 = new TreeNode(6);
TreeNode *p3 = new TreeNode(15);
TreeNode *p4 = new TreeNode(5);
TreeNode *p5 = new TreeNode(7);
TreeNode *p6 = new TreeNode(8);
p1->left = p2;
p1->right = p3;
p2->left = p4;
p2->right = p5;
p5->right = p6;
cout << IsBalance(p1)<<endl;
}
int main()
{
test();
cout << "hello..."<<endl;
return 0;
}