出现次数最多的子树元素和|刷题打卡

264 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

image.png 今天给大家分享的二叉树的题目,先看一下题意,一开始我读了一遍,竟然有点理解错了题意。

题目说的是找到出现次数最多的子树元素和。分成两部分,先找到所有出现的子树元素和,找到出现次数最多的那个,如果出现最多的次数有多个一样的,那么返回所有的对应的子树元素和。而子树元素和指的是以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;
    }

四、总结:

二叉树的题目,递归即可。递归需要考虑递归的结束条件和递归的返回。本文中递归的返回是每个子树的元素和。