[LeetCode] Count Complete Tree Nodes 求完全二叉樹的節點個數
Given a complete binary tree, count the number of nodes.
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is
completely filled, and all nodes in the last level are as far left as
possible. It can have between 1 and 2h nodes inclusive at the last level h.
這道題給定了一棵完全二叉樹,讓我們求其節點的個數。很多人分不清完全二叉樹和滿二叉樹的區別,下面讓我們來看看維基百科上對二者的定義:
A Complete Binary Tree (CBT) is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.
對於一顆二叉樹,假設其深度為d(d>1)。除了第d層外,其它各層的節點數目均已達最大值,且第d層所有節點從左向右連續地緊密排列,這樣的二叉樹被稱為完全二叉樹;
換句話說,完全二叉樹從根結點到倒數第二層滿足完美二叉樹,最後一層可以不完全填充,其葉子結點都靠左對齊。
A Perfect Binary Tree(PBT) is a tree with all leaf nodes at the same depth. All internal nodes have degree 2.
二叉樹的第i層至多擁有個節點數;深度為k的二叉樹至多總共有個節點數,而總計擁有節點數匹配的,稱為“滿二叉樹”;
A Full Binary Tree (FBT) is a tree in which every node other than the leaves has two children.
換句話說,所有非葉子結點的度都是2。(只要你有孩子,你就必然是有兩個孩子。)
通過上面的定義,我們可以看出二者的關係是,完美二叉樹一定是完全二叉樹,而完全二叉樹不一定是完美二叉樹。那麼這道題給的完全二叉樹就有可能是完美二叉樹,若是完美二叉樹,節點個數很好求,為2的h次方-1,h為該完美二叉樹的高度。這道題可以用遞迴和非遞迴兩種方法來解。我們先來看遞迴的方法,思路是分別找出以當前節點為根節點的左子樹和右子樹的高度並對比,如果相等,則說明是滿二叉樹,直接返回節點個數,如果不相等,則節點個數為左子樹的節點個數加上右子樹的節點個數再加1(根節點),其中左右子樹節點個數的計算可以使用遞迴來計算,參見程式碼如下:
class Solution { public: int countNodes(TreeNode* root) { int hLeft = 0, hRight = 0; TreeNode *pLeft = root, *pRight = root; while (pLeft) { ++hLeft; pLeft = pLeft->left; } while (pRight) { ++hRight; pRight = pRight->right; } if (hLeft == hRight) return pow(2, hLeft) - 1; return countNodes(root->left) + countNodes(root->right) + 1; } };
遞迴的解法還有一種解法如下所示:
class Solution { public: int countNodes(TreeNode* root) { int hLeft = leftHeight(root); int hRight = rightHeight(root); if (hLeft == hRight) return pow(2, hLeft) - 1; return countNodes(root->left) + countNodes(root->right) + 1; } int leftHeight(TreeNode* root) { if (!root) return 0; return 1 + leftHeight(root->left); } int rightHeight(TreeNode* root) { if (!root) return 0; return 1 + rightHeight(root->right); } };