首页 > 编程语言 >力扣-968监控二叉树(Java贪心详细题解)

力扣-968监控二叉树(Java贪心详细题解)

时间:2024-09-03 21:56:40浏览次数:12  
标签:right Java 覆盖 int 题解 二叉树 节点 摄像头 left

题目链接:968. 监控二叉树 - 力扣(LeetCode)

前情提要:

本题是一道名副其实的hard题目,他考察二叉树和贪心的综合运用能力。

所以我们不仅要会贪心还要会二叉树的一些知识,如果没有写二叉树类型的题目,建议大家该题可以放放,去刷其他的题目。

因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。

贪心方法:局部最优推出全局最优。

如果一个题你觉得可以用局部最优推出全局最优,并且没有反例来反驳的话就可以用贪心来试试。

题目思路:

本题要求监控树所有节点的最小摄像头数量。我们如何求这个最小摄像头数量呢?

一般遇到二叉树类的题目,遍历顺序很重要,我们如何确认这个遍历顺序呢?

确认遍历顺序

其实从案例我们也会发现,摄像头都没有放在叶子节点,而是放在了叶子节点的父节点。

首先我们要知道一个摄像头所监控的最大范围就是三层。

那么我们怎么最大限度的使用这个条件呢?这就是贪心所在。

我们尽量在叶子节点的父节点设为摄像头 这样可以最大限度的使用摄像头监控三层的条件。

以这个题局部贪心:再每一个叶子节点前面放一个摄像头,再每隔俩个节点再放一个摄像头。

全局最优:所得的摄像头的就是最少的。

那么肯定有人想叶子节点的父节点设摄像头 那我们可不可以在根节点的孩子节点设摄像头呢?

理论也行,但是本题要求最少的摄像头,我们就要最大限度的节省摄像头,由于一个二叉树叶子节点肯定大于等于根节点,处于节约叶子节点的摄像头而言,我们应该从叶子节点出发。

遍历顺序咱们就定下来 就是后序 从叶子节点向上返回结果为父节点。

那么我们如何隔两个节点放一个摄像头

此时需要分析每个节点的状态 三种情况的判定 0 无覆盖 1摄像头 2覆盖。

所以我们得根据左右孩子节点的状态来确认父节点的状态。

但是我们要对二叉树内的null值进行一个特判,null值应该赋给什么状态呢? 答案是赋值为2。为什么赋值为2呢。我们下面讲。

1.左右孩子节点全为2状态 父节点就为 0。

在这里插入图片描述

这里可能互相会想为什么状态为0 为什么不是1 这是因为我们是后序遍历,回溯的过程是从下到上,当孩子节点状态为2 肯定是孩子节点的下层节点出现了 1 此时我们本着最大节约摄像头的原则,他们的父节点就为0,由父节点的父节点为摄像头来将父节点覆盖。

这时我们就想通为什么null值设为2了,当一个孩子为叶子节点,他下一层返回的状态就是俩个2,那他本身应该就是未被覆盖的状态,因为本题的贪心思路就是让叶子节点都为非覆盖状态,让他的父节点为摄像头来监控下面三层的情况。

2.任意孩子节点为1 父节点就是2。

如果任意一个孩子节点被摄像头监控,那父节点就是被覆盖的范围,因为摄像头监控的范围未3层,他可以覆盖他上一层的也就覆盖父节点。

3.任意孩子为 0 父节点就是1。

在这里插入图片描述

如果是以下情况,则中间节点(父节点)应该放摄像头:

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

这个不难理解,毕竟有一个孩子没有覆盖,父节点就应该放摄像头。

特判第四种方式 如果根节点为无覆盖 则将根节点设为1 即设为摄像头。

在这里插入图片描述

所以状态分析完了就可以开始写代码了

最终代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //result用来记录结果
    int result = 0;
    public int minCameraCover(TreeNode root) {
        //temp用来判定第四种情况
        int temp = dfs(root);
        if(temp == 0){
            result ++;
        }
        return result;
        
    }
    public int dfs(TreeNode root){
        //递归三部曲
        //第一步确定方法的返回值和参数
        //后序需要子节点的状态来确认父节点的状态,所以我们需要将返回值设为int
        //第二步确定终止条件
        //遍历树最终会遇到null节点 所以终止条件就是遇到null就不要向下递归了 就该向上返回状态值了
        //第三步确定单层循环逻辑
        if(root == null)return 2;
        //遍历顺序 后序 左右中 即先递归左边 再递归右边 最后处理中间节点
        //左
        int left = dfs(root.left);
        //右
        int right = dfs(root.right);
        //三种情况的判定 0 无覆盖 1摄像头 2覆盖
        //1.当孩子节点全为 2 父节点就为0
        //2.当孩子节点有一个为0 父节点就为1
        //3.当孩子节点有一个为1 父节点就为 2
        if(left == 2&&right == 2)return 0;
        if(left == 0 ||right == 0){
            result ++;
            return 1;
        }
        if(left == 1 ||right == 1)return 2;
        return 0;
    }
}

这到题确实很难,所以需要大家多琢磨琢磨,多模拟几遍。

这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。

我很乐意为你解答。那么我们下篇再见!

标签:right,Java,覆盖,int,题解,二叉树,节点,摄像头,left
From: https://blog.csdn.net/2302_79761426/article/details/141856688

相关文章

  • P01-Java何谓数组
    P01-Java何谓数组一、数组声明创建1.1数组声明的语法与c++有所不同在Java中,数组声明语法首选语法://数据类型[]数组名称;int[]arr;次选,与c++类似//数据类型数组名称[];intarr[];1.2数组创建语法与c++指针有所相似,在java中用new创建数组//数组名称=......
  • Java中的接口
    接口在Java编程中,接口和抽象类是用于定义类行为的两种不同机制。接口是一种行为规范,用来规定类应该遵循的行为和方法,而抽象类则是对行为的抽象,相当于一种模板设计。在本文中,我们将深入探讨接口的特点、使用场景以及在实际编程中的应用。什么是接口接口(Interface)在Java中是一......
  • Java面向对象练习---黑马文字版格斗游戏
    角色类属性:privateStringname;privateintblood;privatechargender;privateStringface;容貌face描述:String[]boyfaces={"风流俊雅","气宇轩昂","相貌英俊","五官端正","相貌平平","一塌糊涂","面目狰狞"}......
  • 【前端面试】leetcode树javascript
    写一个树//定义二叉树节点functionTreeNode(val,left,right){this.val=(val===undefined?0:val)this.left=(left===undefined?null:left)this.right=(right===undefined?null:right)}//示例使用constroot=newTr......
  • [Javascript] Paralle Task
    functiontimeout(time){returnnewPromise((resolve)=>{setTimeout(resolve,time);});}classParalleTask{constructor(paralleCount=2){this.tasks=[];this.paralleCount=paralleCount;this.runningCount=0;}add(......
  • AtCoder ABC 369题解
    前言本题解部分思路来源于网络,仅供参考!A-369题目大意给定\(A\),\(B\)两个整数,求有多少个整数\(x\)使得可以通过某种排列使得\(A\),\(B\),\(x\)为等差数列。解题思路稍加分析即可得到:如果\(A=B\)则结果为\(1\)。如果\(A=B\)但\((A+B)\bmod......
  • 09-03 题解
    09-03题解比赛地址补题地址这回打算改变一下方式,从写"怎么做题"变成"怎么想题"T1什么样的两个\(a_i\)能被合并到一个Bug上?很简单(不过我也想了好一会),mod2同余的两个可以合并在一起为了培养最强Bug,肯定不能往上叠负数,所以上述内容针对序列中的所有正......
  • [蓝桥杯 2018 省 A] 付账问题--贪心题解
    题目重述:[蓝桥杯2018省A]付账问题-洛谷#[蓝桥杯2018省A]付账问题##题目描述几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。现在有$n$个人出去吃饭,他们总共消费了$S$元。其中第$i$个人带了$a_i$元。幸运的是,所有人带的钱的总数是......
  • 蓝桥杯2019省A糖果题解
     附上链接:[蓝桥杯2019省A]糖果-洛谷,有兴趣的小伙伴可以去试试哦~#[蓝桥杯2019省A]糖果##题目描述糖果店的老板一共有$M$种口味的糖果出售。为了方便描述,我们将$M$种口味编号$1$∼$M$。小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而......
  • java 架构师课程资源(资料加源码加课件)
    java架构师课程全程班jvm底层加载内存池与jvm模型垃圾回收器垃圾算法阻塞队列底层源码spring zookeeper等等,需要的话自己点开查看夸克链接https://pan.quark.cn/s/0260673a6657​​​​​​   ......