题目一:输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点一次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:如果根结点存在,那么深度至少为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。但是这种方式重复遍历了树的结点,深度越大的结点,重复的次数越多。这道题与前面求斐波那契数列的情况颇为类似,在那里我们要求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); }