力扣222——完全二叉树的节点个数(二分)
简单的做法是遍历,这里不赘述了;
更快的算法是用位运算+二分;
首先可以快速dfs出节点深度h;
对于完全二叉树来说,节点个数为2^h 到 2^(h+1) - 1之间;
并且具备单增性,可以在这个区间内二分答案;
对于二分出的个数,需要check节点个数在该mid之上还是之下;
对于节点个数x,观察其二进制形式,从第二位开始,其实表示的是该叶子节点的路径(0左1右),例如8,在完全二叉树上,是三次取左子树;
实现上跟二分答案代码相似,check函数部分就是判定跟着该路径到达的叶子节点是否存在;
class Solution {
private:
int level = 0;
TreeNode* R;
public:
int countNodes(TreeNode* root) {
R = root;
if (root == nullptr) return 0;
TreeNode* node = root;
while (node->left != nullptr) {
level++;
node = node->left;
}
int low = 1 << level, high = (1 << (level + 1)) - 1;
while (low <= high) {
int mid = (high + low) >> 1;
if (check(mid)) low = mid + 1;
else high = mid - 1;
}
return low - 1;
}
bool check(int k) {
int x = level;
auto node = R;
while (node != nullptr && x--) {
if (k & (1 << x)) node = node->right;
else node = node->left;
}
return node != nullptr;
}
};