题目一:输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点一次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:如果根结点存在,那么深度至少为1,接下来求左右子树的深度,很明显用递归算法,最后树的深度就是左右子树中深度较大的加上1.
int DepthOfBinaryTree(BinaryTreeNode* pRoot)
{
if(pRoot == NULL)
return 0;
int depthOfLeft = DepthOfBinaryTree(pRoot->m_pLeft);
int depthOfRigth = DepthOfBinaryTree(pRoot->m_pRight);
int longerChild = depthOfLeft > depthOfRigth ? depthOfLeft : depthOfRigth;
return 1 + longerChild;
}
题目二:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
思路:很容易想到对每个结点求深度的办法,对每一个结点,调用之前求深度的函数判断它的左右子树深度相差是否超过1。但是这种方式重复遍历了树的结点,深度越大的结点,重复的次数越多。这道题与前面求斐波那契数列的情况颇为类似,在那里我们要求f(10),用递归的办法就得先求出f(9)和f(8),继而再求f(8)和f(7),这样就产生了很多重复计算。那里的解决办法是改变求和的次序,先求f(1),接着求f(2)…这样顺序递推,就避免了重复求和的情况。那么回到本题上,和斐波那契数列类似,我们先不判断根结点是否平衡,而是判断最深的父结点是否平衡,同时记录结点的深度,接着在往上遍历,判断是否平衡,直到上升到根结点,这样就避免了重复对结点求深度的情况,实际上就是一个后序遍历的过程。
bool IsBalanced(BinaryTreeNode* pRoot, int* depth)
{
if(pRoot == NULL)
{
*depth = 0;
return true;
}
int left, right;
if(IsBalanced(pRoot->m_pLeft, &left) && IsBalanced(pRoot->m_pRight, &right))
{
int diff = left - right;
if(diff <= 1 && diff >= -1)
{
*depth = 1 + (left > right ? left : right);
return true;
}
}
return false;
}
bool IsBalanced(BinaryTreeNode* pRoot)
{
int depth = 0;
return IsBalanced(pRoot, &depth);
}