本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
今天给大家分享的二叉树的题目,先看一下题意,一开始我读了一遍,竟然有点理解错了题意。
题目说的是找到出现次数最多的子树元素和。分成两部分,先找到所有出现的子树元素和,找到出现次数最多的那个,如果出现最多的次数有多个一样的,那么返回所有的对应的子树元素和。而子树元素和指的是以root为根节点的子树本身加上其左右子树的元素和。
二、思路分析:
遇到树的题目,直接递归返回就完事了。因为需要求出现次数最多的,所以我们需要在遍历过程中保存下所有出现过的子树元素和到一个map里。然后遍历一下这个map,找到出现次数最多的key即可,注意key可能包含多个相同的。
递归
-
我们还是从最底层的叶子节点开始往上考虑,考虑每个节点能够提供给父节点的收益是多少。
-
对于每个叶子节点,因为其左右孩子都是NULL,相当于提供的收益都是0,所以递归的返回是root == null时返回0。那么叶子节点能提供给父节点的收益就是叶子节点本身的值。递归函数里返回的是当前子树带来的收益,需要加上root节点本身,即:
root->val + $left + $right;同时需要在遍历到当前子树的时候,记录下来当前子树的元素和到map。 -
时间复杂度:O(N),这里 N 二叉树中节点的个数。
-
空间复杂度:O(H),H是二叉树的高度。
三、AC 代码:
protected $map;
function findFrequentTreeSum($root) {
$this->map = [];
$this->help($root);
$max = PHP_INT_MIN;
$maxV = [];
foreach ($this->map as $key => $cnt) {
if ($cnt > $max) {
$max = $cnt;
}
}
foreach ($this->map as $key => $cnt) {
if ($cnt == $max) {
$maxV[] = $key;
}
}
return $maxV;
}
protected function help($root) {
if ($root == null) {
return 0;
}
$left = $this->help($root->left);
$right = $this->help($root->right);
if (isset($this->map[$left + $right + $root->val])) {
$this->map[$left + $right + $root->val]++;
} else {
$this->map[$left + $right + $root->val] = 1;
}
return $root->val + $left + $right;
}
四、总结:
二叉树的题目,递归即可。递归需要考虑递归的结束条件和递归的返回。本文中递归的返回是每个子树的元素和。