做题的思路是贪心 + 递归。自下而上遍历,每次都在尽可能远的地方安装摄像头,这样得出的就是尽可能少的个数。每个节点都有三种状态,分别表示当前节点不能被监视,当前节点装了摄像头和当前节点可以被监视。
下面用图画了一下自己的思路,分别列举了一下节点存在的各种情况,然后对节点孩子节点的 status 进行分析,一些类似的状态就没有画出来,最后总结画出了左下角的图。
图中横轴为左子树的状态,纵轴为右子树的状态,根据左右子树的状态可以得出父节点的状态。
得出的规律分别是左边黄色框起来的,只要存在一个孩子的 status 为 0 ,节点必须要装摄像头,否则孩子无法被检测到违反题意,也就是if (left == 0 || right == 0) return 1;
。红色框起来的是,只要存在一个孩子的 status 为 1 ,则节点状态为 2 。这里主要是最后一种状态,有一个孩子的 status=2 的时候,如果没有考虑隐藏的信息就会导致误判节点状态为1,这样会导致错误分类。(开始我在这里考虑错了,导致浪费很长时间)
最后剩下的就是 status=0 的可能了,节点的分析到这里就结束了。
但是,在节点中我们让 2,2=》0 的原因是为了让摄像头尽量的少,尽可能让 status=0 的父节点安装摄像头来监控它。但是如果是根节点的 status=0 ,没有父节点来监控它,这样就需要判断 bfs(root)
的值来看是否需要安装摄像头。
最后整理出的代码如下:
public class lc968 {
int count=0;
public int minCameraCover(TreeNode root) {
if(root==null)return 0;
if(root.right==null&&root.left==null)return 1;
if(dfs(root)==0)count++;
return count;
}
/*递归遍历整个树
*status有三个状态:0 不能被监测到;1 自身装了摄像头;2 没装摄像头可以被监视
*/
public int dfs(TreeNode node) {
if (node == null) return 2; //null节点返回2,这样叶子结点的值就是0
int left = dfs(node.left);
int right = dfs(node.right);
if (left == 0 || right == 0) {
count++;
return 1;
}
if (left == 1 || right == 1) return 2;
return 0;
}
}
提交通过。