题目:https://leetcode-cn.com/problems/count-complete-tree-nodes/
思路:
-
遍历
O(N) 遍历整个二叉树 -
使用完全二叉树的性质,减少遍历。
-
利用满二叉树性质:
完全二叉树除了最后一层叶子节点就是满二叉树,满二叉树的节点数量为 2^height - 1,所以我们只需要找到最后一层中的最后一个节点或者第一个空节点就可以算出总数。
O( log 2 \log_2 log2 N)
计算左子树的高度 left_height:遍历最左边
计算右子树的高度 right_height:遍历最右边
如果 left_height == right_height,那么当前树为满二叉树,节点数为 (1 << height) - 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 get_left_height(TreeNode *root) {
if (root == nullptr) {
return 0;
}
return get_left_height(root->left) + 1;
}
int get_right_height(TreeNode *root) {
if (root == nullptr) {
return 0;
}
return get_right_height(root->right) + 1;
}
int countNodes(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int left = get_left_height(root);
int right = get_right_height(root);
if (left == right) {
return (1 << left) - 1;
} else {
return 1 + countNodes(root->left) + countNodes(root->right);
}
}
};
height 不用每次遍历,可以存下来
/**
* 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:
std::unordered_map<TreeNode*, int> node_height;
int get_left_height(TreeNode *root) {
if (root == nullptr) {
return 0;
}
return node_height[root] = node_height.count(root->left) ? node_height[root->left] + 1 : get_left_height(root->left) + 1;
}
int get_right_height(TreeNode *root) {
if (root == nullptr) {
return 0;
}
return node_height[root] = node_height.count(root->right) ? node_height[root->right] + 1 : get_right_height(root->right) + 1;
}
int countNodes(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int left = get_left_height(root);
int right = get_right_height(root);
if (left == right) {
return (1 << left) - 1;
} else {
return 1 + countNodes(root->left) + countNodes(root->right);
}
}
};