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