DAY41:贪心算法(十)监控二叉树

文章目录

    • 968.监控二叉树
      • 思路
        • 遍历顺序
        • 空节点处理
        • 情况列举
      • 最开始的写法
        • debug测试:travelsal的输出多了1
      • 修改版
      • 二叉树注意点
      • 时间复杂度
      • 总结

968.监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

计算监控树的所有节点所需的最小摄像头数量。

在这里插入图片描述
输入:[0,0,null,0,0]
输出:1
解释:如图所示,一台摄像头足以监控所有节点。

在这里插入图片描述
输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。

提示:

  1. 给定树的节点数的范围是 [1, 1000]
  2. 每个节点的值都是 0。

思路

本题一个重要思路是,二叉树中一定是叶子节点数量大于根节点数量的。叶子节点和根节点比起来,数量呈现指数级的扩大,因此我们想要用最少的摄像头,就要在叶子节点上优先想如何节约摄像头

在叶子节点的情况下,我们要优先在叶子节点的父节点上放摄像头,然后一层一层往上推,往上推的逻辑是每隔2个节点放一个摄像头

遍历顺序

因为我们从叶子节点开始,从下往上处理二叉树,所以一定是后序遍历。遍历的同时,我们需要记录每个节点的状态,从而根据左右孩子的状态去确定父节点的状态

这里就涉及到一个状态转移的问题,但是本题的状态转移和动规的状态转移不同,本题只是涉及到一个每个节点状态的判断,并不是要得到最优状态。本题中节点有三种状态:

  • 0:无摄像头,无覆盖
  • 1:有摄像头
  • 2:无摄像头,有覆盖(在摄像头范围内)

我们在后序遍历的时候,可以通过状态转移,来判断左右孩子是某状态的时候,父节点应该是什么状态

空节点处理

本题的目的,就是尽可能让叶子节点的父节点去放摄像头,这样摄像头数目才能最少。为了让叶子节点的父节点能放摄像头,空节点应该是有覆盖的状态。

也就是说,遇到空节点应该向上返回2,这样才能让叶子节点父节点有摄像头。

情况列举

  • 当前节点左右孩子都无摄像头有覆盖,也就是状态2,此时当前节点必然是状态0

在这里插入图片描述

  • 当前节点左右孩子至少有一个无覆盖,此时当前节点一定要装一个摄像头,也就是状态1,否则就不能全覆盖了

在这里插入图片描述

  • 左右孩子至少有一个有摄像头,那么当前节点一定是2

在这里插入图片描述

  • 最后一种情况是基于第一种情况,第一种情况的当前节点无覆盖,需要等待父节点去把他覆盖。但是第一种情况的节点,如果是根节点,就没有父节点可以装摄像头!

    此时根节点本身必须装一个摄像头,否则根节点就是无覆盖的状态。

本题所有可能的情况就限于这四种。主要是分析出来前三种,第四种是遍历到最后对根节点进行单独的判断。

最开始的写法

class Solution {
public://摄像头个数int result=0;//后序遍历,有返回值,返回当前节点状态int travelsal(TreeNode* root){//后序终止条件if(root==nullptr) return 2;//空节点返回状态2//左右中 后序遍历int left = travelsal(root->left);int right = travelsal(root->right);//判断情况,第一种,左右都有cover无摄像头 左右都是状态2if(left==2&&right==2){return 0;//无cover 返回0让父节点加摄像头}//第二种,左右有一个是0if(left==0||right==0){result++;return 1;}//第三种,左右有一个有摄像头if(left==1||right==1){return 2;}//逻辑不会走到这里,只是为了有返回值return -1;}int minCameraCover(TreeNode* root) {travelsal(root);cout<<travelsal(root)<<endl;//第四种,root无cover,但是没有父节点了if(travelsal(root)==0){result++;}return result;}
};

debug测试:travelsal的输出多了1

存在逻辑问题,travelsal的输出多了1

在这里插入图片描述
但是实际上,后序遍历的逻辑是正确的,但是主函数写法出了问题

报错的主函数:

int minCameraCover(TreeNode* root) {travelsal(root);cout<<travelsal(root)<<endl;//第四种,root无cover,但是没有父节点了if(travelsal(root)==0)//if(state==0)result++;return result;}

注意这里的问题是,函数重写一次就会重复运行一次,上面这段主函数代码,相当于travelsal运行了三次

第一次是travelsal(root);,第二次是cout<<travelsal(root)<<endl;,第三次是if(travelsal(root)==0)函数只要出现就会运行一次,而result是一个全局变量,每次运行都会在之前运行的基础上+1.

因此,这里才会出现全局变量是3,但是函数实际逻辑正确的情况,就是因为函数写了三次所以运行了三遍。(这是一个很基础的逻辑问题,函数重新写一次就会运行一次,即使是在cout里面重写,也会运行第二遍,希望下次不要犯这种离谱错误了)

修改版

  • 把主函数写法改掉就可以了
class Solution {
public://摄像头个数int result=0;//后序遍历,有返回值,返回当前节点状态int travelsal(TreeNode* root){//后序终止条件if(root==nullptr) return 2;//空节点返回状态2//左右中 后序遍历int left = travelsal(root->left);int right = travelsal(root->right);//判断情况,第一种,左右都有cover无摄像头 左右都是状态2if(left==2&&right==2){return 0;//无cover 返回0让父节点加摄像头}//第二种,左右有一个是0if(left==0||right==0){result++;return 1;}//第三种,左右有一个有摄像头if(left==1||right==1){return 2;}//逻辑不会走到这里,只是为了有返回值return -1;}int minCameraCover(TreeNode* root) {int state = travelsal(root);cout<<state<<endl;//第四种,root无cover,但是没有父节点了//if(travelsal(root)==0)if(state==0)result++;return result;}
};

或者主函数可以写成

  • 比较简洁的写法,return也可以直接返回表达式,不容易出错
int minCameraCover(TreeNode* root) {int state = travelsal(root);return result+=(state==0?1:0);
}

二叉树注意点

  • 前后序的区别主要在处理节点的顺序,处理当前节点需要下面节点的状态就会用后序,但是所有遍历的终止条件都是遇到空节点返回(也就是触底了才会return),前序也是遇到空节点才开始return
  • 最后return -1 是因为逻辑不会走到这里但是函数需要一个返回值,return什么都可以

时间复杂度

  • 时间复杂度: O(n),需要遍历二叉树上的每个节点
  • 空间复杂度: O(n),本题的空间复杂度在于递归的返回值return输入的二叉树本身是不算空间复杂度的,但是每遍历到一个节点都会return 0/1/2状态值,也就是说每次递归的返回值都占了一个int的内存。所以空间复杂度是return的数值,一共n个数值所以是O(n)

总结

本题的难点首先是要想到贪心的思路,要想得到最少摄像头,就必须在叶子节点的父节点上面放摄像头

然后就是遍历和状态推导,首先要想到二叉树每个节点,都可以归结为三种状态

第二,要想到二叉树每个叶子节点的状态去推当前节点的状态,一共可以归纳为四种情况;然后通过遍历在二叉树上进行状态推导,后序遍历的同时接收下面叶子节点的状态,从而判断出当前的状态和需不需要放置摄像头。

难点在于情况的分析,不要想复杂,所有的情况就是3+1种(最后一种是根节点单独考虑)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/13725.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark学习(二)---Spark运行架构和核心概念

1.Spark运行架构 Spark框架的核心是一个计算引擎&#xff0c;它采用了master-slave的结构。 图形中的 Driver 表示 master&#xff0c; 负责管理整个集群中的作业任务调度。图形中的 Executor 则是 slave&#xff0c;负责实际执行任务。 1.1 核心组件 由此可以得出&#xf…

在原有J-IM基础上改造,开发记录方便日后学习,主要区别加入mysql持久化,但是不完善、仅供参考

在原有J-IM基础上改造&#xff0c;开发记录方便日后学习&#xff0c;主要区别加入mysql持久化&#xff0c;但是不完善、仅供参考 原站地址 https://gitee.com/xchao/j-im 改造后的地址 https://gitee.com/lbx_1397372495/jim-chat 本地启动测试 1&#xff0c;修改mysql 数…

Openlayers鹰眼OverviewMap自定义样式时鹰眼大小调整

Openlayers鹰眼OverviewMap自定义样式时可以根据关注区域的范围长宽比调整鹰眼控件的宽、高大小&#xff0c;让关注的区域始终全部在鹰眼中显示。 如鹰眼控件宽设置100px时 /*鹰眼控件中地图容器的样式*/ .ol-custom-overviewmap .ol-overviewmap-map{border:none;width: 100p…

计算机毕业论文选题推荐|软件工程|小程序系列选题

文章目录 导文题目导文 计算机毕业论文选题推荐|软件工程 (***语言)==使用其他任何编程语言 例如:基于(***语言)门窗账务管理系统的设计与实现 得到:基于JAVA门窗账务管理系统的设计与实现 基于vue门窗账务管理系统的设计与实现 等等 题目 基于微信小程序和深度学习的宠物…

(css)盒子的阴影

(css)盒子的阴影 效果&#xff1a; 代码&#xff1a; box-shadow: inset 0 0 50px 2px #74eaff;解决参考&#xff1a;https://blog.csdn.net/weixin_52984349/article/details/125803515

界面组件DevExpress ASP.NET Core v23.1新版亮点 - 增强的数据可视化

DevExpress ASP.NET Core Controls使用强大的混合方法&#xff0c;结合现代企业Web开发工具所期望的所有功能。该套件通过ASP.NET Razor标记和服务器端ASP.NET Core Web API的生产力和简便性&#xff0c;提供客户端JavaScript的性能和灵活性。ThemeBuilder工具和集成的Material…

DAY40:贪心算法(九)单调递增的数字(贪心的思路)

文章目录 738.单调递增的数字&#xff08;暴力解也需要看一下&#xff09;暴力解写法注意&#xff1a;必须引入isIncreasing变量的原因 贪心思路遍历顺序 最开始的写法debug测试&#xff1a;逻辑错误 修改版debug测试int转化为字符串的原因to_string和stoi的用法 总结 738.单调…

MQTT资料储备

1、官网 https://mqtt.org/ MQTT 5.0官方协议 https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html 说明&#xff1a;官网可以获取到好多资料&#xff08;比如常用软件、协议、usecase等&#xff09; 2、安装部署EMQX 当前有好多MQTT服务器&#xff0c;初步选择了EM…

一键安装和卸载docker及docker-compose

代码&#xff1a; #!/bin/bashSYSTEMD_PATH/usr/lib/systemd/system/docker.service DOCKER_FILEdocker-20.10.23.tgz DOCKER_COMPOSE_FILEdocker-compose-plugin-2.15.1-3.el8.x86_64.rpm RED\E[1;31m GREEN\E[1;32m YELOW\E[1;33m SHAN\E[1;31;5m RES\E[0mfunction install_…

MySQL 8 group by 报错 this is incompatible with sql_mode=only_full_group_by

根据错误信息大概知道&#xff0c;是sql_mode参数设置为only_full_group_by的不兼容&#xff0c;如果select 的字段不在 group by 中&#xff0c;并且select 字段没有使用聚合函数&#xff08;SUM,MAX等&#xff09;&#xff0c;这个sql查询是被mysql认为非法的&#xff0c;会报…

AI视频智慧安监平台EasyCVR每次重启服务短时间播放后又无法播放,是什么原因?

EasyCVR视频融合平台基于云边端智能协同架构&#xff0c;具有强大的设备接入、视频汇聚管理、全网分发、按需调阅、鉴权播放、智能分析等视频能力与服务。平台开放度高、兼容性强、可支持灵活拓展与第三方集成。 有用户反馈&#xff0c;EasyCVR每次重启服务后&#xff0c;可以短…

[MMDetection]VOC数据格式转为COCO数据格式

以下脚本可以根据创建VOC格式数据集转换为COCO数据集 其中文件组织格式如下 VOC2007 ------Annotations ------***********.xml ------***********.xml -------ImageSets ------train.txt ------test.txt -------JPEGImages ------***********.jpg ------***********.jpg CO…