题目:
Given a complete binary tree, count the number of nodes.
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
思路:
1、判断整个树的最底层是否是满的:这是我最开始想到的方法,分别计算该树的最左边结点和最右边结点所在的层深,如果两者相同,则说明整个树的最底层是满的,可以直接返回结果;否则递归处理。这种算法能通过所有测试数据,但是由于在递归的过程中会涉及到重复计算,所以总感觉不是最优的。。。
2、判断左右子树的高度是否相同:这是在网上参考的算法。如果左子树和右子树的高度相同,那么左子树的最底层一定是满的,所以可以直接计算出左子树的结点个数;否则说明右子树的最底层一定是满的,也可以直接计算出右子树的结点个数。所以无论如何,我们都可以在O(1)的时间内立即计算出其中一颗子树的结点个数。接下来递归计算出另外一个子树的结点个数,加在一起再加上1就是整个树的结点个数了。这个算法的递归实现更容易,不过我这里给出迭代实现,效率更高。
代码:
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 countNodes(TreeNode* root) {
if(!root) {
return 0;
}
int height_left = 0, height_right = 0;
TreeNode* left = root;
TreeNode* right = root;
while(left) {
++height_left;
left = left->left;
}
while(right) {
++height_right;
right = right->right;
}
if(height_left == height_right) { // the last layer is full
return pow(2, height_left) - 1;
}
else {
return 1 + countNodes(root->left) + countNodes(root->right);
}
}
};
2、判断左右子树的高度是否相同:
/**
* 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 countNodes(TreeNode* root) {
int ret = 0;
while (root) {
int height_left = getDepth(root->left);
int height_right = getDepth(root->right);
if (height_left != height_right) {
ret += pow(2, height_right);
root = root->left;
}
else {
ret += pow(2, height_left);
root = root->right;
}
}
return ret;
}
private:
int getDepth(TreeNode *root) {
if (root == NULL) {
return 0;
}
return getDepth(root->left) + 1;
}
};