给出一个完全二叉树,求出该树的节点个数。
说明:
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
示例:
输入: 1 / \ 2 3 / \ / 4 5 6 输出: 6
思路一: 最容易的方式,层序遍历做计算。也很好写,在层序遍历的基础上进行累加就可以。问题是内存消耗很高。而且也没有用到完全二叉树的定义,明显这道题让我们借助完全二叉树的性质。
/**
* 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 num=0;
if(root == NULL) return 0;
queue<TreeNode*> roo;
roo.push(root);
while(!roo.empty())
{
TreeNode* tmp=roo.front(); roo.pop();
if(tmp->left) roo.push(tmp->left);
if(tmp->right) roo.push(tmp->right);
num++;
}
return num;
}
};
思路二:虽然我觉得递归还没有层序方便,但是不用占用内存了。
通过上面的定义,我们可以看出二者的关系是,完美二叉树一定是完全二叉树,而完全二叉树不一定是完美二叉树。那么这道题给的完全二叉树就有可能是完美二叉树,若是完美二叉树,节点个数很好求,为2的h次方-1,h为该完美二叉树的高度。这道题可以用递归和非递归两种方法来解。我们先来看递归的方法,思路是分别找出以当前节点为根节点的左子树和右子树的高度并对比,如果相等,则说明是满二叉树,直接返回节点个数,如果不相等,则节点个数为左子树的节点个数加上右子树的节点个数再加1(根节点),其中左右子树节点个数的计算可以使用递归来计算,参见代码如下:
class Solution {
public:
int countNodes(TreeNode* root) {
int hLeft = 0, hRight = 0;
TreeNode *pLeft = root, *pRight = root;
while (pLeft) {
++hLeft;
pLeft = pLeft->left;
}
while (pRight) {
++hRight;
pRight = pRight->right;
}
if (hLeft == hRight) return pow(2, hLeft) - 1;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
class Solution {
public:
int countNodes(TreeNode* root) {
int hLeft = leftHeight(root);
int hRight = rightHeight(root);
if (hLeft == hRight) return pow(2, hLeft) - 1;
return countNodes(root->left) + countNodes(root->right) + 1;
}
int leftHeight(TreeNode* root) {
if (!root) return 0;
return 1 + leftHeight(root->left);
}
int rightHeight(TreeNode* root) {
if (!root) return 0;
return 1 + rightHeight(root->right);
}
};