题目描述
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
(一般来说,平衡二叉树既是平衡的树,又是二分搜索树。但此题只要求判断是不是平衡的)
节点的结构一般如下:
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
方法一
平衡二叉树要求每个节点的左右子树高度相差不能超过1
可以递归进行判断:
- 判断节点的左右子树高度相差是否超过1,超过1则不平衡
- 判断节点左子树是否为平衡二叉树
- 判断节点右子树是否为平衡二叉树
然后问题就在于如何获得树的高度,需要写一个函数获得树的高度,函数int getHeight(TreeNode *node)的思路比较简单,采用了递归方法,如果节点为空,返回0;否则返回1 + max(getHeight(node->left), getHeight(node->right))
代码如下:
int getHeight(TreeNode *node){
if(node == NULL)
return 0;
return 1 + max(getHeight(node->left), getHeight(node->right));
}
整体代码如下:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int getHeight(TreeNode *node){
if(node == NULL)
return 0;
return 1 + max(getHeight(node->left), getHeight(node->right));
}
bool IsBalanced(TreeNode *node){
if(node == NULL)
return true;
if(abs(getHeight(node->left) - getHeight(node->right)) > 1)
return false;
return true;
}
bool IsBalanced_Solution(TreeNode* pRoot) {
if(pRoot == NULL)
return true;
return IsBalanced(pRoot) && IsBalanced(pRoot->left) && IsBalanced(pRoot->right);
}
};
方法二
方法一中对于每个节点都要递归获得其高度,其实很多节点都是重复遍历过的,做了很多重复的操作,所以开始考虑能不能对整棵树只遍历一次得到所有节点的高度。但是获取之后高度的存储是个问题,所以将输入的树进行了复制,然后利用节点的value存储其高度。
复制树函数:TreeNode* CopyTree( TreeNode* root ),基本思路如下:
- 如果节点为空,则返回空
- 节点不为空,则new一个新的节点,新节点value值设为-1
- res->left = CopyTree( root->left );
- res->right = CopyTree( root->right );
TreeNode* CopyTree( TreeNode* root )
{
if( root == NULL )
return NULL;
TreeNode* res = new TreeNode(-1);
res->left = CopyTree( root->left );
res->right = CopyTree( root->right );
return res;
}
求树中每个节点的高度:int GetHeight( TreeNode* root )
- 如果节点为空,则返回0
- 判断节点的val值,如果不等于-1,说明之前已经获取过该节点的高度,可以直接返回其val值
- 否则,返回节点的高度为max( GetHeight(root->left), GetHeight(root->right) ) + 1,将其存入节点的val值,并返回
// 获取高度
int GetHeight( TreeNode* root )
{
if( root == NULL )
return 0;
if( root->val != -1 )
return root->val;
root->val = max( GetHeight(root->left), GetHeight(root->right) ) + 1;
return root->val;
}
获取了树中每个节点的高度后,就可以按照方法一中的思路判断树是否为平衡二叉树
整体代码如下:
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
if( pRoot == NULL )
return true;
TreeNode* newtree = CopyTree(pRoot);
GetHeight(newtree);
return IsBalance(newtree);
}
// 复制树
TreeNode* CopyTree( TreeNode* root )
{
if( root == NULL )
return NULL;
TreeNode* res = new TreeNode(-1);
res->left = CopyTree( root->left );
res->right = CopyTree( root->right );
return res;
}
// 获取高度
int GetHeight( TreeNode* root )
{
if( root == NULL )
return 0;
if( root->val != -1 )
return root->val;
root->val = max( GetHeight(root->left), GetHeight(root->right) ) + 1;
return root->val;
}
// 判断是否为平衡二叉树
bool IsBalance( TreeNode* root )
{
if( root == NULL )
return true;
if( root->left == NULL && root->right == NULL )
return true;
// 没有考虑到左子树为空,右子树高度小于等于1的情况
// if( root->left == NULL && root->right->val >= 2 )
// return false;
// if( root->right == NULL && root->left->val >= 2 )
// return false;
if( root->left == NULL )
return ! (root->right->val >= 2); // 需要打括号,!的优先级高于比较运算符
if( root->right == NULL )
return ! (root->left->val >= 2); // 需要打括号,!的优先级高于比较运算符
if( abs( root->left->val - root->right->val ) >= 2 )
return false;
// 之所以会分这么多情况是因为不确定root的左右子树是否为空,如果为空就取不到val,但是分情况太复杂容易出错,解决方法见后
return IsBalance( root->right )
&& IsBalance( root->left );
}
};
在判断是否为平衡二叉树的函数bool IsBalance( TreeNode* root )中,因为不确定root的左右子树是否为空,如果为空就取不到val,因此分了多种情况进行判断,但这样就很容易出错,所以写了一个int Height(TreeNode* node )函数,返回输入节点的高度,如果输入节点为空则返回0,否则返回其val值,这样就不用在IsBalance函数中判断节点是否为空,就显得更加简洁,不容易出错。
代码如下:
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
if( pRoot == NULL )
return true;
TreeNode* newtree = CopyTree(pRoot);
GetHeight(newtree);
return IsBalance(newtree);
}
// 复制树
TreeNode* CopyTree( TreeNode* root )
{
if( root == NULL )
return NULL;
TreeNode* res = new TreeNode(-1);
res->left = CopyTree( root->left );
res->right = CopyTree( root->right );
return res;
}
// 获得高度
int GetHeight( TreeNode* root )
{
if( root == NULL )
return 0;
if( root->val != -1 )
return root->val;
root->val = max( GetHeight(root->left), GetHeight(root->right) ) + 1;
return root->val;
}
// 获取节点的高度
int Height(TreeNode* node ){
if(node == NULL)
return 0;
return node->val;
}
// 判断是否为平衡二叉树
bool IsBalance( TreeNode* root )
{
if( root == NULL )
return true;
if( abs( Height(root->left) - Height(root->right) ) > 1 )
return false;
return IsBalance( root->right ) && IsBalance( root->left );
}
};
方法三
方法二中虽然不需要对每个节点都重新递归,但需要对树进行复制,占用了额外的空间。事实上,获得树的高度过程以及判断是否为平衡二叉树过程都是需要递归的,可以将两个过程合并,在计算高度的同时判断是否为平衡二叉树,而不需要复制一棵树来存储其高度,函数为int getHeight( TreeNode* root ),在函数内获取左右子树的高度并比较判断是否不平衡,如果平衡,则返回节点的高度,如果不平衡,则返回-1,在递归的上一层,如果getHeight获得的返回值为-1,说明不平衡,可以直接返回-1。
- 如果节点为空,则返回0
- 获取左右子树高度进行存储,判断获取的高度是否为-1,如果等于-1,说明不是平衡二叉树,直接返回-1,
- 如果左右子树高度差大于1,则返回-1,说明不是平衡二叉树
- 否则返回节点的高度max( getHeight(root->left), getHeight(root->right) ) + 1
代码:
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
if( pRoot == NULL )
return true;
int res = getHeight(pRoot);
if( res == -1 )
return false;
return true;
}
int getHeight( TreeNode* root )
{
if( root == NULL )
return 0;
int left = getHeight(root->left);
if( left == -1 )
return -1;
int right = getHeight(root->right);
if( right == -1 )
return -1;
if( abs(left - right) > 1 )
return -1;
return max( getHeight(root->left), getHeight(root->right) ) + 1;
}
};