Given a complete binary tree, count the number of nodes.
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.
对于完全二叉树,去掉最后一层,就是一棵满二叉树,我们知道高度为 h 的满二叉树结点的个数为 2^h - 1 个,所以要知道一棵完全二叉树的结点个数,只需知道最后一层有多少个结点。而完全二叉树最后一层结点是从左至右连续的,所以我们可以依次给它们编一个号,然后二分搜索最后一个叶子结点。我是这样编号的,假设最后一层在 h 层,那么一共有 2^(h-1) 个结点,一共需要 h - 1 位来编号,从根结点出发,向左子树走编号为 0, 向右子树走编号为 1,那么最后一层的编号正好从0 ~ 2^(h-1) - 1。复杂度为 O(h*log(2^(h-1))) = O(h^2)。下面是AC代码。
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 bool isOK(TreeNode *root, int h, int v) { 13 TreeNode *p = root; 14 for (int i = h - 2; i >= 0; --i) { 15 if (v & (1 << i)) p = p->right; 16 else p = p->left; 17 } 18 return p != NULL; 19 } 20 21 int countNodes(TreeNode* root) { 22 if (root == NULL) return 0; 23 TreeNode *p = root; 24 int h = 0; 25 while (p != NULL) { 26 p = p->left; 27 ++h; 28 } 29 int l = 0, r = (1 << (h - 1)) - 1, m; 30 while (l <= r) { 31 m = l + ((r - l) >> 1); 32 if (isOK(root, h, m)) l = m + 1; 33 else r = m - 1; 34 } 35 return (1 << (h - 1)) + r; 36 } 37 };
或者可以用递归的方法,对于这个问题,如果从某节点一直向左的高度 = 一直向右的高度, 那么以该节点为root的子树一定是complete binary tree. 而 complete binary tree的节点数,可以用公式算出 2^h - 1. 如果高度不相等, 则递归调用 return countNode(left) + countNode(right) + 1. 复杂度为O(h^2)。
该方法参考:http://blog.csdn.net/xudli/article/details/46385011
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 int getHeight(TreeNode *root, bool tag) { 13 int h = 0; 14 while (root != NULL) { 15 if (tag) root = root->left; 16 else root = root->right; 17 ++h; 18 } 19 return h; 20 } 21 22 int countNodes(TreeNode* root) { 23 if (root == NULL) return 0; 24 int left = getHeight(root, true); 25 int right = getHeight(root, false); 26 if (left == right) return (1 << left) - 1; 27 else return countNodes(root->left) + countNodes(root->right) + 1; 28 } 29 };