监控二叉树

监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。

示例 1:

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

示例 2:

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

贪心
首先确定遍历方式,在安排选择摄像头的位置的时候,我们要从底向上进行推导,因为尽量让叶子节点的父节点安装摄像头,这样摄像头的数量才是最少的 ,这也是本道贪心的原理所在!
如何从低向上推导呢?就是后序遍历也就是左右中的顺序,这样就可以从下到上进行推导了

确定了遍历顺序,再看看这个状态应该如何转移,先来看看每个节点可能有几种状态:
可以说有如下三种:

  • 该节点无覆盖(0)
  • 本节点有摄像头(1)
  • 本节点有覆盖(2)

那么问题来了,空节点究竟是哪一种状态呢? 空节点表示无覆盖? 表示有摄像头?还是有覆盖呢?
回归本质,为了让摄像头数量最少,我们要尽量让叶子节点的父节点安装摄像头,这样才能摄像头的数量最少。
那么空节点不能是无覆盖的状态,这样叶子节点就可以放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。
所以空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了

单层逻辑处理主要有如下四类情况:

  • 情况1:左右节点都有覆盖
    左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。

  • 情况2:左右节点至少有一个无覆盖的情况
    如果是以下情况,则中间节点(父节点)应该放摄像头:
    left == 0 && right == 0 左右节点无覆盖
    left == 1 && right == 0 左节点有摄像头,右节点无覆盖
    left == 0 && right == 1 左节点有无覆盖,右节点摄像头
    left == 0 && right == 2 左节点无覆盖,右节点覆盖
    left == 2 && right == 0 左节点覆盖,右节点无覆盖
    此时摄像头的数量要加一,并且 return 1,代表中间节点放摄像头。

  • 情况3:左右节点至少有一个有摄像头
    如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
    left == 1 && right == 2 左节点有摄像头,右节点有覆盖
    left == 2 && right == 1 左节点有覆盖,右节点有摄像头
    left == 1 && right == 1 左右节点都有摄像头
    情况4:头结点没有覆盖
    以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况,如图:

    所以递归结束之后,还要判断根节点,如果没有覆盖,result++

private int res;

public int minCameraCover(TreeNode root) {
    return dfs(root) == 0 ? res + 1 : res;
}

// 监控完root的子树,root的状态
// 0:无覆盖 1:有摄像头 2:有覆盖 
private int dfs(TreeNode root) {
    if (root == null) {
        return 2;
    }
    int left = dfs(root.left);
    int right = dfs(root.right);
    if (left == 2 && right == 2) {
        return 0;
    }
    if (left == 0 || right == 0) {
        res++;
        return 1;
    }
    return 2;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值