监控二叉树(基于二叉树的动态规划)(后序遍历的进阶)

Posted 秦枫-_-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了监控二叉树(基于二叉树的动态规划)(后序遍历的进阶)相关的知识,希望对你有一定的参考价值。


解题思路:
这道题目其实不是那么好理解的,题目举的示例不是很典型,会误以为摄像头必须要放在中间,其实放哪里都可以只要覆盖了就行。

这道题目难在两点:

需要确定遍历方式
需要状态转移的方程
我们之前做动态规划的时候,只要最难的地方在于确定状态转移方程,至于遍历方式无非就是在数组或者二维数组上。

本题并不是动态规划,其本质是贪心,但我们要确定状态转移方式,而且要在树上进行推导,所以难度就上来了,一些同学知道这道题目难,但其实说不上难点究竟在哪。

需要确定遍历方式
首先先确定遍历方式,才能确定转移方程,那么该如何遍历呢?

在安排选择摄像头的位置的时候,我们要从底向上进行推导,因为尽量让叶子节点的父节点安装摄像头,这样摄像头的数量才是最少的 ,这也是本道贪心的原理所在!

如何从低向上推导呢?

就是后序遍历也就是左右中的顺序,这样就可以从下到上进行推导了。
需要状态转移的方程
确定了遍历顺序,再看看这个状态应该如何转移,先来看看每个节点可能有几种状态:

可以说有如下三种:

该节点无覆盖
本节点有摄像头
本节点有覆盖
我们分别有三个数字来表示:

0:该节点无覆盖
1:本节点有摄像头
2:本节点有覆盖
大家应该找不出第四个节点的状态了。

一些同学可能会想有没有第四种状态:本节点无摄像头,其实无摄像头就是 无覆盖 或者 有覆盖的状态,所以一共还是三个状态。

那么问题来了,空节点究竟是哪一种状态呢? 空节点表示无覆盖? 表示有摄像头?还是有覆盖呢?

回归本质,为了让摄像头数量最少,我们要尽量让叶子节点的父节点安装摄像头,这样才能摄像头的数量最少。

那么空节点不能是无覆盖的状态,这样叶子节点就可以放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。

所以空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了

接下来就是递推关系。

那么递归的终止条件应该是遇到了空节点,此时应该返回 2(有覆盖)
递归的函数,以及终止条件已经确定了,再来看单层逻辑处理。

主要有如下四类情况:

情况1:左右节点都有覆盖
左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。

如图:

情况2:左右节点至少有一个无覆盖的情况
如果是以下情况,则中间节点(父节点)应该放摄像头:

left == 0 && right == 0 左右节点无覆盖
left == 1 && right == 0 左节点有摄像头,右节点无覆盖
left == 0 && right == 1 左节点有无覆盖,右节点摄像头
left == 0 && right == 2 左节点无覆盖,右节点覆盖
left == 2 && right == 0 左节点覆盖,右节点无覆盖

这个不难理解,毕竟有一个孩子没有覆盖,父节点就应该放摄像头。
此时摄像头的数量要加一,并且 return 1,代表中间节点放摄像头。

情况3:左右节点至少有一个有摄像头
如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)

left == 1 && right == 2 左节点有摄像头,右节点有覆盖
left == 2 && right == 1 左节点有覆盖,右节点有摄像头
left == 1 && right == 1 左右节点都有摄像头
情况4:头结点没有覆盖
以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况,如图:

//0  无覆盖,1 有摄像头,2 有覆盖
class Solution 
    int ans=0;
    public int minCameraCover(TreeNode root) 
     int tmp=dfs(root);
     if(tmp==0)ans++;
     return ans;
    
    public int dfs(TreeNode root)
        if(root==null)
         return 2;
        
        int left=dfs(root.left);
        int right=dfs(root.right);
        if(left==2&&right==2)return 0;
        if(left==0||right==0)
        ans++;
        return 1;
        
        if(left==1||right==1)return 2;
        return 0;
    


以上是关于监控二叉树(基于二叉树的动态规划)(后序遍历的进阶)的主要内容,如果未能解决你的问题,请参考以下文章

Luna Tech | 二叉树的前序中序后序遍历

Leetcode刷题100天—145. 二叉树的后序遍历(二叉树)—day08

二叉树进阶题------前序遍历和中序遍历构造二叉树;中序遍历和后序遍历构造二叉树

二叉树进阶题------前序遍历和中序遍历构造二叉树;中序遍历和后序遍历构造二叉树

LeetCode 145. 二叉树的后序遍历 (用栈实现后序遍历二叉树的非递归算法)

每日一扣145. 二叉树的后序遍历