题目
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
示例 1:
输入:root = [1,2,3,4,5,6] 输出:6
示例 2:
输入:root = [] 输出:0
示例 3:
输入:root = [1]
输出:1
提示:
- 树中节点的数目范围是
[0, 5 * 104]
0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
题解
方法一:深度优先遍历所有节点,但未使用完全二叉树的性质
class Solution {
public:
void countNodes(TreeNode* root){
if(!root) return 0;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
方法二:使用完全二叉树相关性质
class Solution {
public:
// 统计树的深度
int countLevels(TreeNode* root) {
int levels = 0;
while (root) {
root = root->left; levels += 1;
}
return levels;
}
int countNodes(TreeNode* root){
// 2. 利用完全二叉树性质简化遍历次数
if(root == nullptr) return 0;
int left_levels = countLevels(root->left);
int right_levels = countLevels(root->right);
// 左子树深度等于右子树深度, 则左子树是满二叉树
if(left_levels == right_levels){
return countNodes(root->right) + (1<<left_levels);
}else{
return countNodes(root->left) + (1<<right_levels);
}
}
};
方法三:使用二分查找+位运算实现
class Solution {
public:
int countLevels(TreeNode* root){
int levels = 0;
TreeNode* node = root;
while(node->left!=nullptr){
levels++;
node = node->left;
}
return levels;
}
int countNodes(TreeNode* root) {
if(root == nullptr){
return 0;
}
int levels = countLevels(root);
int low = 1<<levels,high = (1<<(levels+1))-1;
while(low<high){
int mid = high+low+1>>1;
if(exist(root,levels,mid)){
low = mid;
}else{
high = mid-1;
}
}
return low;
}
bool exist(TreeNode* root,int levels,int k){
int bits = 1<<(levels-1);
TreeNode* node = root;
while(node!=nullptr && bits>0){
if((bits&k)==0){
node = node->left;
}else{
node = node->right;
}
bits>>=1;
}
return node!=nullptr;
}
};
方法四:使用递归遍历左右子树
class Solution {
public:
int getNum(TreeNode* cur){
if(cur == nullptr){
return 0;
}
int left = getNum(cur->left);
int right = getNum(cur->right);
return left + right +1;
}
int countNodes(TreeNode* root) {
return getNum(root);
}
};