968.监控二叉树

困难程度,二叉树题型
题目描述:给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。

分析

首先分析解题方法,我的理解是,类似高考之前咱们的刷题,每一种题型应该是由类似固定的解题思路,也就是模板套路;这里是关于二叉树的题目,一想到二叉树,我们首先应该想到的是递归解题,然后应该想到的是如何进行树的遍历————先序,中序还是后续?根据不同的题目,应该是采用不同的遍历方式进行递归调用。本题难度为hard,难点就在于,在二叉树的基础上,这里面要考虑状态的变化,有点像动态规划的状态转移方程,因为我们可以思考一下,每一节点的状态主要有三种状态:被覆盖(2),没有被覆盖(0),以及放监视器(1).不同状态用不同的数字进行标注。根据题目意思,要尽可能的使监视器的数目最小,那么监视器应该尽量放到每一次遍历时叶子节点的父节点上去,所以遍历方式我们采用后续遍历,根据叶子节点的状态,我们再决定父节点的状态。
接下来是最难的一部,我们需要考虑所有叶子节点可能的情况,然后推算出父节点的状态。这里面主要有以下几种情况:

  • 左右子节点被覆盖
    - 这种情况下,父节点不用装监视器,状态为未被覆盖;
  • 左右节点至少一个未覆盖
    - 因为要使所有节点覆盖,为了使叶子节点被覆盖,父节点必须装监视器;
  • 左右节点至少一个装了监视器(另一个是被覆盖的,未覆盖在上一种情况被包含)
    - 这种情况,父节点肯定是被覆盖

根据以上分析,下面的代码可以很好的被理解了

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int result = 0;
public:
    int minCameraCover(TreeNode* root) {
        if(travel(root) == 0)
            result++;
        return result;
    }
    // travel函数遍历以当前节点为根节点时,当前节点的状态
    int travel(TreeNode* cur){
        if(cur == NULL) return 2;
        int left = travel(cur->left);
        int right = travel(cur->right);

        if((left==2) && (right==2)){
            return 0;
        }
        if((left==0) || (right==0)){
            result++;
            return 1;
        }
        if((left==1)||(right==1)){
            return 2;
        }
        return -1;
    }
};

这里面注意的是,root的状态,最后要判断一下,如果是0,得另外加上监视器

posted @ 2020-09-22 20:48  青衣素  阅读(178)  评论(0)    收藏  举报