https://leetcode.cn/problems/binary-tree-cameras/
题目要求
给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。
贪心
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int res = 0;
public int minCameraCover(TreeNode root) {
// 情况4:头结点没有覆盖
if (dfs(root) == 0)
res++;
return res;
}
public int dfs(TreeNode root) {
// 0:该节点无覆盖
// 1:本节点有摄像头
// 2:本节点有覆盖
if (root == null)
return 2;
// 主要有如下四类情况:
int left = dfs(root.left);
int right = dfs(root.right);
// 情况1:左右节点都有覆盖
// 左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
if (left == 2 && right == 2)
return 0;
// 情况2:左右节点至少有一个无覆盖的情况
// 如果是以下情况,则中间节点(父节点)应该放摄像头:
// left == 0 && right == 0 左右节点无覆盖
// left == 1 && right == 0 左节点有摄像头,右节点无覆盖
// left == 0 && right == 1 左节点有无覆盖,右节点摄像头
// left == 0 && right == 2 左节点无覆盖,右节点覆盖
// left == 2 && right == 0 左节点覆盖,右节点无覆盖
// if ((left == 0 && right == 0) || (left == 1 && right == 0) || (left == 0 && right == 1) || (left == 0 && right == 2 || (left == 2 && right == 0))) {
// res++;
// return 1;
// }
if (left == 0 || right == 0) {
res++;
return 1;
}
// 情况3:左右节点至少有一个有摄像头
// 如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
if (left == 1 || right == 1)
return 2;
return -1;
}
}
- 摄像头可以覆盖上中下三层,如果把摄像头放在叶子节点上,就浪费的一层的覆盖。所以把摄像头放在叶子节点的父节点位置,才能充分利用摄像头的覆盖面积。
- 所以我们要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!
- 大体思路就是从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。