968. 监控二叉树(递归+贪心)

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

示例 1:
在这里插入图片描述

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

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

提示:

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

————————————————————————————————————————————————————————
题目要求最小摄像头数目,如果从头节点开始看,就只能省一个摄像头,而如果从叶子节点开始看,就可以省下指数级的摄像头数目;
所以可以确定遍历顺序是从叶子节点开始向上遍历,让叶子节点的父节点装摄像头即可;
很容易想到是后序遍历,根据贪心思想有:
局部最优:叶子节点的父节点安摄像头,所用摄像头最少;
全局最优:整体二叉树所用摄像头最少;

然后该考虑装摄像头的情况了,这里需要考虑每个节点可能的状态,有三种:
1,有摄像头覆盖
2,没有摄像头覆盖
3,有摄像头

注意:这里“没有摄像头”状态就是1和2了;

所以可以用三个数字表示节点状态:
0:该节点无覆盖
1:该节点有摄像头
2:该节点有覆盖

这里还需要考虑一点:空节点怎么办?(终止条件)
空节点如果是没有覆盖状态,那么叶节点就得有摄像头,所以我们需要将空节点赋为有覆盖的状态;

整个递归函数整体框架有了,接下来是每一层的逻辑情况,有四种:
1,左孩子和右孩子都有覆盖(2),那么父节点就需要是无覆盖状态(0)
2,左孩子和右孩子至少有一个没有覆盖,那么父节点就需要是有摄像头状态(1)
3,左孩子和右孩子至少有一个有摄像头,那么父节点就需要是有覆盖的状态(2)
4,头节点没有覆盖,那么需要单独给它加一个摄像头;

分析完了,代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int ans = 0;
    //0:无覆盖 1:有摄像头 2:有覆盖
    int traverse(TreeNode* root) {
        if (!root) return 2;
        int left = traverse(root -> left);
        int right = traverse(root -> right);
        //情况二
        if (!left || !right) {
            ans++;
            return 1;
        }
        //情况三
        if (left == 1 || right == 1) {
            return 2;
        }
        //情况一
        if (left == 2 && right == 2) {
            return 0;
        }
        return -1;
    }
    int minCameraCover(TreeNode* root) {
        //情况四
        if (!traverse(root)) {
            ans++;
        }
        return ans;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YXXYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值