力扣 968. 监控二叉树

跳转至 监控二叉树icon-default.png?t=LA92https://leetcode-cn.com/problems/binary-tree-cameras/

题目

        给定一个二叉树,我们在树的节点上安装摄像头。

        节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

        计算监控树的所有节点所需的最小摄像头数量。

示例 1:


输入:[0,0,null,0,0]
输出:1
解释:如图所示,一台摄像头足以监控所有节点。
示例 2:


输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。

提示:

给定树的节点数的范围是 [1, 1000]。
每个节点的值都是 0。

题解

        一般这种情况多样的首先都会想到用动态规划去求解,关键在于如何找到状态转移公式和处理边界问题。

        假设当前的节点为root,其左右孩子节点分别记为left、right,要使三者都被检测到的话可以分为两种情况:

        1. 在root上放置摄像头,那么left和right都可以被检测到,目前只需保证left的子树和right的子树被检测到即可。

        2. 不在root上放置摄像头,那么left和right必定需要放置摄像头,且需保证left的子树和right的子树被检测到。

        综上所述,我们可以将root的状态分为三种:

        状态a:在root上放置节点,保证root子树都被检测到的摄像头数目。

        状态b:覆盖整个子树所需的摄像头数目。

        状态c:只保证root子树都被检测到的摄像头数目,不保证root是否被检测到。

        设三种状态对应的左右子树所需的摄像头数目为 l_{a},l_{b},l_{c} 和 r_{a},r_{b},r_{c}

        对于状态a,可以推导出 a=l_{c}+r_{c}+1 (状态c的左子树和右子树的总摄像头数目+1,保证root放置了摄像头);

        对于状态b,可以推导出 b=min(a, min(l_{a}+r_{b},l_{b}+r_{a})) (状态a可能不是最优解,那么还需比较其余两种符合的结果);

        对于状态c,可以推导出 c=min(a,l_{b} + r_{b}) (对于状态c,状态a和状态b都符合状态c的条件,取其二最小值)。

        最后一步处理边界,当root为空的时候,那么将不需要放置摄像头。对于状态b和状态c而言是无需比较状态a的值的,所以状态a的结果返回Infinity。

function minCameraCover(root: TreeNode | null): number {
    function dfs(root: TreeNode | null): [number, number, number] {
        // 当root为空的时候,那么将不需要放置摄像头。对于状态b和状态c而言是无需比较状态a的值的,所以状态a的结果返回Infinity。
        if(!root) return [Infinity, 0, 0]
        const [la, lb, lc] = dfs(root.left)
        const [ra, rb, rc] = dfs(root.right)
        const a: number = lc + rc + 1
        const b: number = Math.min(a, Math.min(la + rb, ra + lb))
        const c: number = Math.min(a, lb + rb)
        return [a, b ,c]
    }
    // 我们最终需要的答案为状态b
    return dfs(root)[1]
};

执行效率如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值