监控二叉树
leetcode 968.监控二叉树
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
例
解法
要解决本问题需要确定两点
1.遍历方式
2.状态转移方程
1.遍历方式
本问题需要从底向上进行遍历,尽量让叶子节点的父节点安装监控才能让监控的数量最少,所以可以选择后序遍历的方式,可以先定义代码大体框架
private int dfs(TreeNode node){
if(终止条件/空节点) return;
int l = dfs(node.left);
int r = dfs(node.right);
//其他逻辑
}
2.状态转移方程
首先可以确定节点的状态,主要有三种状态
0.该节点没有被覆盖
1.该节点安装了监控
2.该节点被覆盖
再来讨论终止条件,也就是空节点的问题,当节点为空时我们可以认为该节点为状态2,因为是从底向上遍历,则他的父节点则为状态0,以最少监控的原则,他的爷爷节点需要安装监控为状态1。
则当为空节点时,可以返回2,表示该节点被覆盖
if(node == null){
return 2;
}
确定了终止条件,接下来可以分几个情况来讨论:
情况1
左右字节点都被覆盖,则这个节点是无覆盖状态
if(l == 2 && r == 2){
return 0;
}
情况2
如果左或右节点无覆盖,则这个节点需要放监控
if(l == 0 || r == 0){
res++;//res用来记录监控数量
return 1;
}
情况3
如果左节点或右节点有监控,则这个节点已被覆盖
if(l == 1 || rigth == 1){
return 2;
}
情况4
遍历完成后,还需要判断根节点,如果根节点状态为0,也就是没有被覆盖,则需要放监控
将以上四种情况整理,最终代码为
class Solution {
int result = 0;
public int minCameraCover(TreeNode root) {
//情况4.根节点无覆盖,则需要放监控
if(dfs(root) == 0){
result++;
}
return result;
}
//定义三种状态
//0.无覆盖
//1.有监控
//2.有覆盖
//采用后续遍历的思想,先确定子节点,再确定父节点
private int dfs(TreeNode node){
//如果节点为null,则可以认为他已覆盖,他的父节点是无覆盖,而他的爷爷节点需要放监控
if(node == null)
return 2;
int left = dfs(node.left);
int right = dfs(node.right);
//情况1.左右子节点都有覆盖
if(left == 2 && right ==2)
return 0;
//情况2.左子节点或右子节点无覆盖,则这个点需要放监控
if(left == 0 || right == 0){
result++;
return 1;
}
//情况3.左子节点或右子节点有监控,则这个节点已经有覆盖
if(left == 1 || right == 1){
return 2;
}
return -1;
}
}