题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一颗平衡二叉树。
方法一:
在遍历树的每个节点额度时候,调用函数TreeDepth得到它的左右子树的深度。如果每个节点左右子树的深度相差都不超过1,那么按照定义它就是一棵平衡二叉树。
int TreeDepth(const BinaryTreeNode* pRoot)
{
if(pRoot == nullptr)
return 0;
int nLeft = TreeDepth(pRoot->m_pLeft);
int nRight = TreeDepth(pRoot->m_pRight);
return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}
bool IsBalanced_Solution1(const BinaryTreeNode* pRoot)
{
if(pRoot == nullptr)
return true;
int left = TreeDepth(pRoot->m_pLeft);
int right = TreeDepth(pRoot->m_pRight);
int diff = left - right;
if(diff > 1 || diff < -1)
return false;
return IsBalanced_Solution1(pRoot->m_pLeft)
&& IsBalanced_Solution1(pRoot->m_pRight);
}
- 上面的代码固然简洁,但我们也要注意到由于一个节点会被重复遍历多次,这种思路的时间效率不高。
方法二:
- 每个结点只遍历一次的解法,正是面试官喜欢的。
如果我们用后序遍历的方式遍历二叉树的每个节点,那么在遍历到一个结点之前我们将就已经遍历了它的左右子树。只要在遍历每个结点的时候记录它的深度(某一节点的深度等于它到叶节点的路径的长度),我们就可以一边遍历以便判断每个结点是不是平衡的。
bool IsBalanced_Solution2(const BinaryTreeNode* pRoot)
{
int depth = 0;
return IsBalanced(pRoot, &depth);
}
bool IsBalanced(const BinaryTreeNode* pRoot, int* pDepth)
{
if(pRoot == nullptr)
{
*pDepth = 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)
{
*pDepth = 1 + (left > right ? left : right);
return true;
}
}
return false;
}
- 用后序遍历的方式遍历整课二叉树。在遍历某结点的左右子结点之后,我们可以根据它的左右子结点的深度判断它是不是平衡的,并得到当前结点的深度。当最后遍历到树的根结点的时候,也就判断了整棵二叉树是不是平衡二叉树。