LeetCode 分类刷题:1448. 统计二叉树中好节点的数目

题目

给你一棵根为 root 的二叉树,请你返回二叉树中好节点的数目。

「好节点」X 定义为:从根到该节点 X 所经过的节点中,没有任何节点的值大于 X 的值。

解析

我的思路:

// 从根开始深度遍历每个节点,计数器初始值为0
// 记录从根到当前节点经过路径中的最大值
// 如果最大值都不超过当前节点的值,则计数器加1

  • count 是外部变量,在闭包中被所有递归调用共享

  • 每次遇到 good node 时直接修改外部变量 count++

  • 递归函数没有返回值,只是通过副作用修改外部状态

灵神思路(官方题解也是):

递归递归,先「递」后「归」。

我们可以在向下递归的同时,额外维护一个参数 mx 表示从根节点到当前节点之前,路径上的最大节点值。

  • 如果当前节点为空,到达递归边界,返回 0。
  • 递归左子树 goodNodes(root.left, max(mx, root.val)),获取左子树的好节点个数 left。
  • 递归右子树 goodNodes(root.right, max(mx, root.val)),获取右子树的好节点个数 right。
  • 如果当前节点是好节点,即 mx <= root.val,那么返回 left+right+1。否则返回 left+right。

作者:灵茶山艾府
链接:https://leetcode.cn/problems/count-good-nodes-in-binary-tree/solutions/2403677/jian-ji-xie-fa-pythonjavacgojs-by-endles-gwxt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

答案

我的写法:只有"递",没有"归"

  • :在向下递归的过程中,通过外部变量 count 直接记录结果

  • 没有归:递归函数没有返回值,不通过返回值向上传递信息

答案写法:完整的"递"和"归"

  • :向下传递 路径上的最大节点值 信息

  • :向上返回子树的结果进行累加

我的答案(这种写法属于带信息“递”,但是没有“归”)

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var goodNodes = function(root) {
    // 从根开始深度遍历每个节点,计数器初始值为0
    // 记录从根到当前节点经过路径中的最大值
    // 如果最大值都不超过当前节点的值,则计数器加1
    if(root === null) return 0;
    let count = 0;
    function dfs(node, maxVal) {
        if(node === null) return;
        if(maxVal <= node.val) {
            count++;
            maxVal = node.val;
        }
        dfs(node.left, maxVal);
        dfs(node.right, maxVal);
    }
    dfs(root, -Infinity);
    return count;
};

根据官方题解思路写的答案

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var goodNodes = function(root) {
    // 对于每个节点:
    // 当前节点的count = 当前节点自身是否是good node(0或1) 
    //                 + 左子树的good nodes数量 
    //                 + 右子树的good nodes数量
    if(root === null) return 0;
    function dfs(node, maxVal) {
        if(node === null) return 0;
        let count = 0;
        if(maxVal <= node.val) {
            count++;
            maxVal = node.val;
        }
        count += dfs(node.left, maxVal) + dfs(node.right, maxVal);
        return count;
    }
    return dfs(root, -Infinity);
};

灵神答案

var goodNodes = function (root, mx = -Infinity) {
    if (root === null)
        return 0;
    const left = goodNodes(root.left, Math.max(mx, root.val));
    const right = goodNodes(root.right, Math.max(mx, root.val));
    return left + right + (mx <= root.val);
};

// 作者:灵茶山艾府
// 链接:https://leetcode.cn/problems/count-good-nodes-in-binary-tree/solutions/2403677/jian-ji-xie-fa-pythonjavacgojs-by-endles-gwxt/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度分析

时间复杂度:O(n),其中 n 为二叉树的节点个数。每个节点都会递归恰好一次。
空间复杂度:O(n)。最坏情况下,二叉树是一条链,递归需要 O(n) 的栈空间。

作者:灵茶山艾府
链接:https://leetcode.cn/problems/count-good-nodes-in-binary-tree/solutions/2403677/jian-ji-xie-fa-pythonjavacgojs-by-endles-gwxt/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值