具体思路:
想到了从下向上保留状态,但是没想到是三状态;
感觉是见过树状态遍历见过最难的题了;
这里一定要注意,每个节点有三个状态:
- 根结点覆盖,整棵树所需要的最小监视器个数;
- 根结点可以不覆盖,整棵树所需要的最小监视器个数;
- 保证左右子树全覆盖,根结点覆盖与否都可以;
此时,后续遍历,某个节点必定会收到l1,l2,l3和r1,r2,r3;
此时进行本届节点的三个状态计算;
- 第一种情况根节点覆盖,左右子树的根节点就没必要覆盖了,所以为l3+r3+1;
- 第二种情况根节点不覆盖,要么左子树根节点覆盖,要么右子树根节点覆盖,要么是第一种情况,所以三者取最小;
- 第三种情况左右子树要求全覆盖,只需要l2+r2即可;
具体代码:
/**
* 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) {}
* };
*/
//a 根结点覆盖下,整棵树所需要的最小监视器
//b 根结点覆盖不覆盖都行,整棵树所需要的最小监视器树;
//c 覆盖左右子树,跟节点腹部覆盖都可以;
class Solution {
public:
int minCameraCover(TreeNode* root) {
auto vec=dfs(root);
return vec[1];
}
vector<int> dfs(TreeNode* root){
if(!root){
return {INT_MAX/2,0,0};
}
vector<int> left=dfs(root->left);
vector<int> right=dfs(root->right);
int a=1+left[2]+right[2];//跟节点如果覆盖,则左右节点不用覆盖,覆盖他们的子节点即可;
int b=min(a,min(left[0]+right[1],right[0]+left[1]));
int c=min(a,left[1]+right[1]);
return {a,b,c};
}
};```