222.完全二叉树的节点个数**(优先掌握递归)**
题目
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2(h)
个节点。
示例:
输入:root = [1,2,3,4,5,6]
输出:6
提示:
-
树中节点的数目范围是
[0, 5 * 10(4)]
-
0 <= Node.val <= 5 * 10(4)
-
题目数据保证输入的树是 完全二叉树
思路
普通二叉树解法
用求二叉树遍历模板稍微修改一下,记录遍历的节点数量就好,遍历顺序依然是后序(左右中)
完全二叉树思路
完全二叉树:除了底层节点,其他节点都是满的,底层节点从左到右一字排开
若最底层为第 n 层,则该层包含 1~ 2 h − 1 2^{h-1} 2h−1个节点
完全二叉树两种情况
- 满二叉树
用 2^树深度 - 1 来计算,根节点深度为 1
- 最后一层叶子节点没有满
分别递归左孩子和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后根据情况 1 来计算
如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算子树(满二叉树)的节点数量
关键在于,在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,就是满二叉树,如图
如果不等于,就不是满二叉树
一个常见误区是考虑到这种情况,但下图这种情况并不是一个完全二叉树
代码实现
普通二叉树
- 定义函数 int getNum(node){
- 终止条件: if(node == NULL)return 0;
- leftnum = getNum(node->left) //左
- rightnum = getNum(noed->right) //右
- result = leftNum + rightNum + 1; //中
- return result;
class Solution {
private:
int getNodesNum(TreeNode* cur) {
if (cur == NULL) return 0;
int leftNum = getNodesNum(cur->left); // 左
int rightNum = getNodesNum(cur->right); // 右
int treeNum = leftNum + rightNum + 1; // 中
return treeNum;
}
public:
int countNodes(TreeNode* root) {
return getNodesNum(root);
}
};
- 精简: return getNum(left) + getNum(right) + 1;
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == NULL) return 0;
return 1 + countNodes(root->left) + countNodes(root->right);
}
};
完全二叉树
- int getNum(node){
- if(node == NULL) return 0;
- left = node->left;
- right = node->right;
- leftdepth = 0; rightdepth = 0;
- while(left){
- left = left->left;
- leftdepth++;
- while(right){
- right = right->right;
- rightdepth++;
- if(leftdepth == rightdepth)
- return (2<<leftedpth) - 1
- leftNum = getNum(node->left) //左
- rightNum = getNum(node->right) //右
- result = leftNum + rightNum + 1 //中
class Solution {
public:
int countNodes(TreeNode* root) {
if(root == nullptr)return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int rightDepth = 0, leftDepth = 0;
while(left){
left = left->left;
leftDepth++;
}
while(right){
right = right->right;
rightDepth++;
}
if(leftDepth == rightDepth)return (2<<leftDepth) - 1;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};