题目一:二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
链接:
剑指Offer(第2版):P271
思路标签:
- 算法:递归
解答:
- 将问题分解成子问题,递归地去求解;
- 整颗二叉树的深度为根结点的节点1加上max(左子树的深度,右子树的深度)。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot == nullptr)
return 0;
int nLeft = TreeDepth(pRoot->left);
int nRight = TreeDepth(pRoot->right);
return (nLeft > nRight)? (nLeft + 1):(nRight +1);
}
};
题目二:平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。如果某二叉树中任意节点的左、右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
链接:
剑指Offer(第2版):P273
思路标签:
- 算法:递归、后序遍历
解答:
1. 在上题的基础上求解(时间复杂度高)
- 求出左右子树的长度,如果长度差绝对值大于1,就不是平衡二叉树;
- 递归地进行求解,但是一个节点会被多次遍历,时间复杂度很高。
class Solution {
public:
bool isBalance(TreeNode* pRoot) {
if (pRoot == nullptr)
return true;
int left = TreeDepth(pRoot->left);
int right = TreeDepth(pRoot->right);
int diff = left - right;
if (diff > 1 || diff < -1)
return false;
return isBalance(pRoot->left) && isBalance(pRoot->right);
}
int TreeDepth(TreeNode* pRoot)
{
if (pRoot == nullptr)
return 0;
int nLeft = TreeDepth(pRoot->left);
int nRight = TreeDepth(pRoot->right);
return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}
};
2. 每个节点只遍历一次的解法
- 使用后序遍历,在遍历一个节点前就已经遍历了其左右子树;
- 在遍历的过程中记录子树的深度。
- 每个节点只遍历一遍,复杂度低。
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
int depth = 0;
return isBalanced(pRoot, depth);
}
bool isBalanced(TreeNode* pRoot, int& depth){
if(pRoot == nullptr){
depth = 0;
return true;
}
int left, right;
if(isBalanced(pRoot->left, left) && isBalanced(pRoot->right, right)){
int diff = left - right;
if(diff<=1 && diff>=-1){
depth = 1 + (left>right? left:right);
return true;
}
}
return false;
}
};