题目
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/
9 20
/
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/
2 2
/
3 3
/
4 4
返回 false 。
思路一:递归记录每个结点的高度+层序遍历检查高度差
不过这样的效率较低,毕竟遍历了两遍。
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int getDepth(TreeNode* node){if(node == NULL) return 0;int left=getDepth(node->left);int right=getDepth(node->right);node->val = max(left,right)+1;return max(left,right)+1;}bool isBalanced(TreeNode* root) {getDepth(root);queue<TreeNode*> que;if(root!=NULL) que.push(root);int num=0;while(!que.empty()){//该层结点元素个数 = 该层队列元素int size = que.size();//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();if(node->left && node->right){if(abs(node->left->val - node->right->val)>1){return false;}}if(node->left && !node->right){if(node->left->val>1){return false;}}if(!node->left && node->right){if(node->right->val>1){return false;}}//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}}return true;}
};
参考其他思路
概念辨析:
二叉树结点的深度:指从根结点到该结点的最长简单路径边的条数
二叉树结点的高度:指从该结点到叶结点的最长简单路径边的条数
leetcode中强调的深度和高度很明显是按照结点来计算。
深度是从上到下去查,所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能使用后序遍历(左右中)。
根结点的最大深度就是这个根结点的高度。
递归三部曲分析:
1、确定递归参数和返回值
参数:传入的结点指针
返回值:返回传入结点为根结点的树的高度。
如果已经不是二叉平衡树了可以返回-1进行标记。
//-1 表示已经不是平衡二叉树了,否则返回值就是以该节点为更急诶·根结点的树的高度(最大深度)
int getDepth(TreeNode* node)
2、明确终止条件
遇到空结点终止,返回0
if(node ==NULL) return 0 ;
3、明确单层逻辑
1、如果左子树不是平衡二叉树,返回-1
2、如果右子树不是平衡二叉树,返回-1
3、如果左右子树的高度差大于1,返回-1
4、否则,返回结点高度
int leftDepth = getDepth(node->left);
if(leftDepth == -1) return -1;
int rightDepth= getDepth(node->right);
if(rightDepth== -1) return -1;
if(abs(leftDepth - rightDepth)>1) return -1;
else return 1+max(leftDepth,rightDepth);
4、完整递归代码
int getDepth(TreeNode* node)
{if(node ==NULL) return 0 ;int leftDepth = getDepth(node->left);if(leftDepth == -1) return -1;int rightDepth= getDepth(node->right);if(rightDepth== -1) return -1;if(abs(leftDepth - rightDepth)>1) return -1;else return 1+max(leftDepth,rightDepth);
}
5、举例分析
以左侧为例:
4:高度为 1
3:高度为 2
2:高度为3,它的左子树高度为2,右子树高度为0,高度差大于1,所以非平衡树。
下面是我写的错误的代码,原因是对平衡二叉树的理解出现了差错,是两个子树的高度差大于1。
而且考虑到出现一次非平衡状态就直接返回-1,一直返回到原结点,从而减少时间浪费。
错误代码:
int getDepth(TreeNode* node) { if(node == NULL) return 0; int left=getDepth(node->left); int right=getDepth(node->right); if(node->left && node->right) { if(abs(left-right)>1) { return -1; } } if(node->left && !node->right) { if(left>1) { return -1; } } if(!node->left && node->right) { if(right>1) { return -1; } } return max(left,right)+1; }
AC代码:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int getDepth(TreeNode* node){if(node ==NULL) return 0 ;int leftDepth = getDepth(node->left);if(leftDepth == -1) return -1;int rightDepth= getDepth(node->right);if(rightDepth== -1) return -1;if(abs(leftDepth - rightDepth)>1) return -1;else return 1+max(leftDepth,rightDepth);}bool isBalanced(TreeNode* root) {if(getDepth(root)==-1) return false;return true;}
};
总结
了解了二叉树的深度与高度的差异,求深度适合用前序遍历,求高度适合用后序遍历。