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.
最简单的方法s1:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right;` * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int countNodes(TreeNode* root) { return count_nodes(root); } int count_nodes(TreeNode* root) { if (root == NULL) { return 0; } int cnt = 1; cnt += count_nodes(root->left) + count_nodes(root->right); return cnt; } };
当然TLE了
改进后s2:
因为完全二叉树如果去掉最后最后一层,那么剩下的这H-1层组成的树就是一颗满二叉树,不用去数其中的节点,直接可以计算得出为(2^(H-1))-1个,所以只要求出最后一层的节点个数加上即可。
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right;` * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int countNodes(TreeNode* root) { if (root == NULL) { return 0; } int elen = 0; TreeNode* cur = root; while (cur != NULL) { elen++; cur = cur->left; } // amount of nodes above last level in the tree int cnt = (1<<(elen-1)) - 1; return cnt + last_level_count(root, elen); } int last_level_count(TreeNode* root, int elen) { if (root == NULL || elen <= 0) { return 0; } if (elen == 1) { return 1; } TreeNode* cur = root->left; int lcnt = elen - 1; while (cur != NULL) { lcnt--; cur = cur->right; } // left sub-tree is not full, no need to compute right sub-tree if (lcnt != 0) { return last_level_count(root->left, elen - 1); } // left sub-tree is full int level_count_left_subtree = 1<<(elen - 1 - 1); int level_count_right_subtree= last_level_count(root->right, elen - 1); return level_count_left_subtree + level_count_right_subtree; } };
last_level_count函数可以考虑实现为非递归形式。
超简洁版本S3:
class Solution { public: int countNodes(TreeNode* root) { if(!root) return 0; int hl=0, hr=0; TreeNode *l=root, *r=root; while(l) {hl++;l=l->left;} while(r) {hr++;r=r->right;} if(hl==hr) return pow(2,hl)-1; return 1+countNodes(root->left)+countNodes(root->right); } };
来自discuss,时间上和第二种一样