目录
-
平衡二叉树(剑指欧肥儿)
题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
解题代码一:
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
//排除特殊情况
if(pRoot == NULL) return true;
int leftTreeDep = getDepth(pRoot -> left);
int rightTreeDep = getDepth(pRoot -> right);
if(leftTreeDep - rightTreeDep > 1 || rightTreeDep - leftTreeDep > 1){
return false;
}
return IsBalanced_Solution(pRoot -> left) && IsBalanced_Solution(pRoot -> right);
}
int getDepth(TreeNode* pRoot){
//排除特殊情况
if(pRoot == NULL) return 0;
//递归算高度
int leftDepth = getDepth(pRoot -> left);
int rightDepth = getDepth(pRoot -> right);
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
//return max(leftDepth + 1,rightDepth + 1); 这句和上面一句的return完全等效
}
};
解题关键:
- 平衡二叉树的特点,它可以是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且它的左右两个子树都是一颗平衡二叉树。
- 单独写出一个计算树的高度的函数getDepth()
- 运用了两个递归,一个计算树的高度,一个判断每个子树是否满足平衡二叉树的特征。
解题代码二:
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
//排除特殊情况
return getDepth(pRoot) != -1;
}
int getDepth(TreeNode* pRoot){
//排除特殊情况
if(pRoot == NULL) return 0;
//递归算高度
int leftDepth = getDepth(pRoot -> left);
if(leftDepth == -1) return -1;
int rightDepth = getDepth(pRoot -> right);
if(rightDepth == -1) return -1;
return abs(leftDepth - rightDepth) > 1 ? -1 : 1 + max(leftDepth, rightDepth);
}
};
解题关键:
- 代码一是对树从上到下,对每层的左右节点进行计算树高度,每一次计算高度,都会重复计算下面的节点的高度,其实是没必要的。
- 代码二是对树从下到上(递归是从下开始递归的),计算每一个节点的高度,但没有重复计算任何一个节点的高度。
- 代码二是对代码一的改进,避免的不必要的计算,但思考量和难度更大。
题外话:
- C++中取绝对值的函数,int abs(int x),在这里不用引入库,可能牛客这个剑指的编译器引入了cmath库。
- C++取两个数的最大值的函数是 int max(int x,int y)
- 上面两个函数都要在,include<cmath> 的前提下
-
二叉树的深度(剑指欧肥儿)
题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
解题代码:
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot == NULL) return 0;
int left = TreeDepth(pRoot -> left);
int right = TreeDepth(pRoot -> right);
return max(left + 1,right + 1);
//return left > right ? left + 1 : right + 1;
}
};
解题思路:
- 这个代码其实是上一道题的代码一的第二个函数getDepth,而return max(left + 1, right + 1)和上一道题的代码一getDepth的return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;是一个道理,两者完全可以相互替换。
- 这里要说一次,树的深度,结点的层数是从根开始定义起,根为第一层,根的孩子是第二层,以此类推。树中结点的最大层次称为树的深度(Depth)。
题外话:
要被if的判断条件判断为false的语句有,if(NULL) if(0) if(false)
-
二叉树的下一个结点(剑指欧肥儿)
题目描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解题代码:
/*
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
*/
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
//排除不可能
if(pNode == NULL) return NULL;
//如果该节点有右子节点
TreeLinkNode* p = NULL;
if(pNode -> right != NULL){
p = pNode -> right;
while(p -> left != NULL){
p = p -> left;
}
}
//如果该节点没有右节点
else if(pNode -> next != NULL){
//该节点还是父亲节点的右节点
TreeLinkNode* pp;
p = pNode;
pp = p -> next;
while(p == pp -> right && pp != NULL){
p = pp;
pp = pp -> next;
}
p = pp;
}
return p;
}
};
解题思路:
- 这道题思路比较难,看了 答案也会想很久。
- 对于一个节点,对它进行分了三个类。
a:该节点有右节点,则它的下一个节点是它的右子树的最左节点。
b:该节点没有右节点,该节点还是它父节点的右节点,则我们沿着该节点的父亲节点一路往上遍历,直到找到一个节点x,x是它父亲节点的左节点。