思路
- 一直靠着左边往下走,那么肯定能到最左边的叶子节点
- 问题的关键在于确定剩下的节点数量,等于求最下面一层叶子节点的数量
- 使用二分查找,确定“存在状态”的节点的最右侧(也就是
right = mid - 1
求右边界的二分查找) - 现在的问题在于,如何确定节点的存在状态
- 可以将节点标号,第0层为
1
,第1层从左到右10 11
,第2层:100 101 110 111
,等于按照层次往下标号,走左边就标0,走右边标1。通过序号去遍历这棵树,从而判断是不是存在指定位置的节点。
LC222. 完全二叉树的节点个数
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool exist(TreeNode* root, int num) {
TreeNode* node = root;
// 先定位到最高位
int highest = 0;
for (int i = 0; i < 31; i++) {
if (num & (1 << (31 - i))) {
highest = 31 - i;
break;
}
}
for (int i = highest - 1; i >= 0; i--) {
if (node == nullptr) {
break;
}
if (((num >> i) & 1) == 0) {
node = node->left;
} else {
node = node->right;
}
}
return node != nullptr;
}
int countNodes(TreeNode* root) {
TreeNode* node = root;
if (!root) {
return 0;
}
int level = 0;
while (node->left) {
level++;
node = node->left;
}
int left = (1 << level), right = (1 << (level + 1)) - 1;
while (left < right) {
int mid = (left + right + 1) / 2;
if (exist(root, mid)) {
left = mid;
} else {
right = mid - 1;
}
}
return right;
}
};