一、题目分析
题目要求统计二叉树中满足 "节点值等于其所在子树平均值" 的节点数量。子树平均值的计算规则为:子树所有节点值之和 ÷ 子树节点总数。
示例解析
以输入 root = [4,8,5,0,1,null,6] 为例:
- 节点 4 的子树包含 6 个节点,总和为 24,平均值为 4,与节点值相等,符合条件。
- 节点 5 的子树包含 2 个节点,总和为 11,平均值为 5,与节点值相等,符合条件。
- 叶子节点 0、1、6 的子树仅包含自身,平均值等于节点值,均符合条件。 最终输出结果为 5。
二、解题思路
核心思路是后序遍历二叉树,因为计算子树的平均值需要先获取左、右子树的节点总和与节点数,再结合当前节点的值进行计算。具体步骤如下:
-
递归遍历左子树,获取左子树的节点总和与节点数。
-
递归遍历右子树,获取右子树的节点总和与节点数。
-
计算当前节点所在子树的总和(左子树总和 + 右子树总和 + 当前节点值)与节点数(左子树节点数 + 右子树节点数 + 1)。
-
计算子树平均值,判断是否与当前节点值相等,若相等则统计结果加 1。
-
将当前子树的总和与节点数返回给上层递归。
#include
#include
using namespace std;// 二叉树节点定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};class Solution {
private:
int result = 0; // 统计符合条件的节点数// 后序遍历辅助函数,返回当前子树的总和与节点数 pair<int, int> postOrder(TreeNode* root) { if (root == nullptr) { return {0, 0}; // 空节点返回总和0,节点数0 } // 递归遍历左子树 auto [leftSum, leftCount] = postOrder(root->left); // 递归遍历右子树 auto [rightSum, rightCount] = postOrder(root->right); // 计算当前子树的总和与节点数 int currentSum = leftSum + rightSum + root->val; int currentCount = leftCount + rightCount + 1; // 判断当前节点值是否等于子树平均值 if (root->val == currentSum / currentCount) { result++; } // 返回当前子树的总和与节点数给上层 return {currentSum, currentCount}; }public:
int averageOfSubtree(TreeNode* root) {
postOrder(root);
return result;
}
};// 测试代码
int main() {
// 构建示例二叉树
TreeNode* root = new TreeNode(4);
root->left = new TreeNode(8);
root->right = new TreeNode(5);
root->left->left = new TreeNode(0);
root->left->right = new TreeNode(1);
root->right->right = new TreeNode(6);Solution sol; cout << "符合条件的节点数:" << sol.averageOfSubtree(root) << endl; // 输出5 // 释放内存(可选,避免内存泄漏) delete root->left->left; delete root->left->right; delete root->right->right; delete root->left; delete root->right; delete root; return 0;}
四、代码说明
- 二叉树节点结构 :使用
TreeNode结构体定义二叉树节点,包含节点值、左子节点指针和右子节点指针。 - 后序遍历函数 :
postOrder函数通过递归实现后序遍历,返回值为pair<int, int>,分别表示子树的总和与节点数。 - 统计逻辑 :在计算完当前子树的总和与节点数后,判断节点值是否等于子树平均值,若相等则将
result加 1。 - 测试代码 :构建题目示例中的二叉树,调用
averageOfSubtree函数并输出结果。
五、复杂度分析
- 时间复杂度:O (n),其中 n 为二叉树的节点数,每个节点仅被遍历一次。
- 空间复杂度:O (h),其中 h 为二叉树的高度,递归栈的深度取决于树的高度。