题目
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组.
示例 1:
输入:
3
/ \
9 20
/ \
15 7
输出: [3, 14.5, 11]
解释:
第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11].
注意:
- 节点值的范围在32位有符号整数范围内。
思路
解释:题目中的 32位有符号整数
,不要多想,就是 double
。
题目要求我们返回一个数组,其中每个元素对应的就是一层节点的平均值。
想要求出平均值,就要先求出总和;想要求出总和,就要让存储不出错;怎样让存储不出错?关键就是先处理好每一个节点与层数的对应关系。
讲得不太好,将就着听听吧。
你可以理解为,下面的程序用的是层序遍历
,这里我是选择用一个队列实现。
——精深细剖析
首先,我们将根节点放入队列 q
中,随后对于 q
,我们进行一轮轮有规律的操作:对于在本轮操作一开始,存在于 q
中的每一个节点,我们将它的子节点放入队尾,然后将其弹出。将本轮操作一开始就存在于 q
中的所有节点都处理完毕后,我们惊奇地发现,该轮弹出的所有节点同处于树的一层,这就很好地解决了节点与层数对应关系的问题。
——本题的思路十分巧妙,看懂以上这段话,你会惊奇地发现,对于这种思路,我们完全可以在弹出节点时,将该点的值加入 sum
中,然后再取平均值就很容易了。
有人会问这样一个问题:怎么判断一个队列中的节点,是否在本轮操作一开始就处于队列中呢?
(——这个问题十分重要)
很简单,我们在一轮操作的一开始,就将队列的长度记录下来,只要弹出操作的次数不超过它,就证明当前节点在本轮操作一开始就处于队列中。
你们期待已久的代码终于来了:
/**
* 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:
vector<double> ans;
vector<double> averageOfLevels(TreeNode* root) {
if(!root) return ans;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()) {
int num = 0, n = q.size(); //变量n很好地解决了问题
double sum = 0;
while(num < n) { //弹出次数不超过一开始的队列长度
TreeNode* t = q.front(); q.pop(); //弹出节点
sum += t -> val; //将该弹出节点的值放入sum
if(t -> left) q.push(t ->left); //将左子节点放入队尾
if(t -> right)q.push(t -> right);//将右子节点放入队尾
num ++; //弹出次数增加
}
ans.push_back(sum / n); //计算平均值并加入答案中
}
return ans;
}
};
制作不易,点个赞呗~