监控二叉树
学习记录自代码随想录
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
要点:1.想到优先覆盖叶子节点,即让叶子节点的父节点有摄像头;
2.想到每个节点有三种状态0-无覆盖,1-摄像头,2-有覆盖;
3.优先覆盖叶子节点,需要从下到上遍历,用后序遍历左右中;
4.四种情况:a.左右节点都有覆盖,则中间节点为无覆盖;b.左右节点至少一个无覆盖,则中间节点为摄像头1;c.左右节点至少一个摄像头,则中间节点为有覆盖;d.最后判断根节点是否为无覆盖,若是,还要添加一个摄像头到根节点;
5.首先是要想到贪心的思路,然后就是遍历和状态推导,此题较难,很难直接想到。
cpp
/**
* 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 result;
int traversal(TreeNode* cur){
//节点状态:0-无覆盖,1-摄像头,2-有覆盖
// 空节点:为有覆盖2, 因为尽量保证叶子节点的父节点有摄像头,所以空节点只能为有覆盖2
if(cur == nullptr) return 2;
// 尽量保证叶子节点被覆盖,即叶子节点父节点要有摄像头,所以遍历为后序遍历
int left = traversal(cur->left);
int right = traversal(cur->right);
// 1.左右节点均为有覆盖2,则中间节点为无覆盖0
if(left == 2 && right == 2) return 0;
// 2.左右节点至少一个为无覆盖0,则中间节点为摄像头1
if(left == 0 || right == 0){
result++;
return 1;
}
// 3.左右节点至少一个有摄像头,则中间节点为有覆盖2
if(left == 1 || right == 1) return 2;
return -1; // 上述代码未使用else,所以逻辑不会走到这里,仅作形式此处
}
int minCameraCover(TreeNode* root) {
// 局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!
result = 0;
// 4.如果最后根节点无覆盖,则需要多一个摄像头
if(traversal(root) == 0){
result++;
}
return result;
}
};