image.png

思路

  • 一直靠着左边往下走,那么肯定能到最左边的叶子节点
  • 问题的关键在于确定剩下的节点数量,等于求最下面一层叶子节点的数量
  • 使用二分查找,确定“存在状态”的节点的最右侧(也就是right = mid - 1求右边界的二分查找)
  • 现在的问题在于,如何确定节点的存在状态
  • 可以将节点标号,第0层为1,第1层从左到右10 11,第2层:100 101 110 111,等于按照层次往下标号,走左边就标0,走右边标1。通过序号去遍历这棵树,从而判断是不是存在指定位置的节点。

image.pngLC222. 完全二叉树的节点个数

代码

  1. /**
  2. * Definition for a binary tree node.
  3. * struct TreeNode {
  4. * int val;
  5. * TreeNode *left;
  6. * TreeNode *right;
  7. * TreeNode() : val(0), left(nullptr), right(nullptr) {}
  8. * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
  9. * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
  10. * };
  11. */
  12. class Solution {
  13. public:
  14. bool exist(TreeNode* root, int num) {
  15. TreeNode* node = root;
  16. // 先定位到最高位
  17. int highest = 0;
  18. for (int i = 0; i < 31; i++) {
  19. if (num & (1 << (31 - i))) {
  20. highest = 31 - i;
  21. break;
  22. }
  23. }
  24. for (int i = highest - 1; i >= 0; i--) {
  25. if (node == nullptr) {
  26. break;
  27. }
  28. if (((num >> i) & 1) == 0) {
  29. node = node->left;
  30. } else {
  31. node = node->right;
  32. }
  33. }
  34. return node != nullptr;
  35. }
  36. int countNodes(TreeNode* root) {
  37. TreeNode* node = root;
  38. if (!root) {
  39. return 0;
  40. }
  41. int level = 0;
  42. while (node->left) {
  43. level++;
  44. node = node->left;
  45. }
  46. int left = (1 << level), right = (1 << (level + 1)) - 1;
  47. while (left < right) {
  48. int mid = (left + right + 1) / 2;
  49. if (exist(root, mid)) {
  50. left = mid;
  51. } else {
  52. right = mid - 1;
  53. }
  54. }
  55. return right;
  56. }
  57. };