给出一个完全二叉树,求出该树的节点个数。
说明:
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
示例:
输入: 1 / \ 2 3 / \ / 4 5 6 输出: 6
题解:
一开始同学问我我还以为是一道简单的树的遍历,结果一交就直接T了,时间复杂度是O(n)也就一组很坑很大的数据没过,后来想了想,优化思路如下:由于是完全二叉树,节点个数可以直接得出为最后一层的节点个数+pow(2,deep-1)-1,其中deep为二叉树的最大深度,这个可以在遍历过程中求出,然后设置一个tag,初始为0,设置一个deep记录最大深度,初始为0,sum记录最后一层的节点个数。从根节点往下进行前序遍历,每当到一个既没有左儿子又没有右儿子的节点,sum++,检查当前深度dep是否大于等于deep,如果是,就更新下deep(其实就只要第一次获得最大深度就行了),如果不是,直接tag=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 sum=0,deep=1,tag=0;
int countNodes(TreeNode* root) {
if(root==NULL)
return 0;
if(root->left==NULL&&root->right==NULL)
return 1;
findNode(root,1);
int s=sum+pow(2,deep-1)-1;
return s;
}
void findNode(TreeNode* root,int dep)
{
if(tag)
return;
if(root->left==NULL&&root->right==NULL)
{
if(deep<=dep)
{
deep=dep;
sum++;
}
else
{
tag=1;
}
return;
}
if(root->left!=NULL)
findNode(root->left,dep+1);
if(root->right!=NULL)
findNode(root->right,dep+1);
}
};