題目: 輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。
分析:首先要明白平衡二叉樹的概念:
平衡二叉樹必須滿足兩個條件:1)左右子樹的高度差不能大於1 2)每個根節點下面的左右子樹也必須滿足平衡二叉樹的性質。
對於本題,我們首先要知道如何去求一棵二叉樹的深度,接下來我們只需要判斷每個節點是否滿足平衡二叉樹的性質不就完了。所以就有了第一種方法的出現。
但是第一種方法有一個問題就是,有些節點會被重復遍歷,為了克服這個問題,我們可以一邊遍歷一邊判斷每個節點是否平衡。
struct BinaryTreeNode{ int m_value; BinaryTreeNode * p_leftTreeNode; BinaryTreeNode * p_rightTreeNode; }; int GetTreeDepth(BinaryTreeNode* pNode) { if (pNode == NULL) return 0; int nLeft, nRight; if (pNode->p_leftTreeNode != NULL) nLeft = GetTreeDepth(pNode->p_leftTreeNode) + 1; if (pNode->p_rightTreeNode != NULL) nRight = GetTreeDepth(pNode->p_rightTreeNode) + 1; return (nLeft > nRight) ? nLeft : nRight; } //1.時間復雜度為 O((logn)!) ,其中有些節點被重復遍歷了,效率不高 bool isBalanced(BinaryTreeNode *pNode) { if (pNode == NULL) return true; //判斷為平衡二叉樹必須滿足兩個條件 //條件1,一個節點的左右子樹之間的高度差必須小於等於1 int nLeftDepth = GetTreeDepth(pNode->p_leftTreeNode); int nRightDepth = GetTreeDepth(pNode->p_rightTreeNode); int nDiffInDepth = nLeftDepth - nRightDepth; if (nDiffInDepth<-1 || nDiffInDepth>1) return false; //條件2.一個節點下面的左右子樹分別也要滿足平衡二叉樹的要求 return (isBalanced(pNode->p_leftTreeNode) && (isBalanced(pNode->p_rightTreeNode))); } //2.更好的方法,這里很好的解決了第一種方法的問題,就是遍歷每個節點的時候,我們用pDepth記錄其深度, //那么我們就可以一邊遍歷一邊判斷每個節點是不是平衡的 bool isBalanced(BinaryTreeNode* pNode,int *pDepth) { if (pNode == NULL) { return true; *pDepth = 0; } int nLeft, nRight; int nDiffInDepth; if (isBalanced(pNode->p_leftTreeNode, &nLeft) && isBalanced(pNode->p_rightTreeNode, &nRight)) { nDiffInDepth = nLeft - nRight; if (nDiffInDepth >= -1 && nDiffInDepth <= 1) { *pDepth = nLeft > nRight ? nLeft : nRight + 1; return true; } } return false; } bool isBalanced(BinaryTreeNode* pNode) { int nDepth = 0; //深度最開始初始化為0 return isBalanced(pNode, &nDepth); }
