剑指Offer——平衡二叉树

题目描述

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

(一般来说,平衡二叉树既是平衡的树,又是二分搜索树。但此题只要求判断是不是平衡的)

节点的结构一般如下:

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 )

扫描二维码关注公众号,回复: 2596380 查看本文章
  • 如果节点为空,则返回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;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36132127/article/details/81193183