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