学习了一段时间《剑指offer》现在做了一些笔试,现在陆续把笔记上传到博客,方便自己及他人上网查看。
题目一:输入一颗二叉树的根结点,求该树的深度。从根节点到叶节点经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
利用递归代码如下:
struct BinaryTreeNode{
int m_data;
BinaryTreeNode* p_LNode;
BinaryTreeNode* p_RNode;
};
int GetDepthForBinaryTree(BinaryTreeNode* pRoot)
{
if (pRoot == NULL)
return 0;
int lhs_numbers = GetDepthForBinaryTree(pRoot->p_LNode);
int rhs_numbers = GetDepthForBinaryTree(pRoot->p_RNode);
return (lhs_numbers>rhs_numbers) ? (lhs_numbers + 1) : (rhs_numbers + 1);
题目二:输入一颗二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么他就是一颗平衡二叉树。例如,图6.1中的二叉树就是一颗平衡二叉树。
有了求深度的函数,我们思路如下:在遍历树的时候,调用函数GetDepthBinaryTree得到他的左子树,右子树深度。如果每个节点的左右子树深度之差不超过1,那么就是平衡二叉树。
bool IsBalanced(BinaryTreeNode* pRoot)
{
if (pRoot == NULL)
return true;
int left = GetDepthForBinaryTree(pRoot->p_LNode);
int right = GetDepthForBinaryTree(pRoot->p_RNode);
int diff = left - right;
if (diff > 1 || diff < -1)
return false;
return IsBalanced(pRoot->p_LNode) && IsBalanced(pRoot->p_RNode);
}
上述的代码中,可以发现每一个结点都可能被遍历多次,这种思路的时间效率不高。书上的不需要重复遍历的思路如下:
思路:在遍历到一个结点之前我们就已经遍历了,它的左右子树。只要在遍历每个结点的时候记录它的深度,我们就可以避免重复多次遍历结点,下面是这种思路的代码:
bool IsBalanced_(BinaryTreeNode* pRoot, int* pDepth)
{
if (pRoot == NULL)
{
*pDepth = 0;
return true;
}
int left, right;
if (IsBalanced_(pRoot->p_LNode, &left) && IsBalanced_(pRoot->p_RNode, &right))
{
int diff = left - right;
if (diff <= 1 && diff >= -1)
{
*pDepth = 1 + (left > right ? left : right);
return true;
}
}
return false;
}
我们只需要给上面的函数传入二叉树的根节点及一个表示结点深度的整数型变量即可;
bool IsBalanced_Core(BinaryTreeNode* pRoot)
{
int depth = 0;
return IsBalanced_(pRoot, &depth);
}
在上面的代码中,我们用后序遍历的方式遍历整颗二叉树,在遍历某结点的左右结点之后,我们可以根据他的左右子节点的深度判断是不是平衡的,并得到当前节点的深度,当最后遍历到树的根节点的时候,也就判断了整颗二叉树是不是平衡二叉树。