968.监控二叉树 树上最小支配集

 法一: 动态规划

一个被支配的节点只会有三种状态

        1.它本身有摄像头

        2.他没有摄像头, 但是它的父节点有摄像头

        3.他没有摄像头, 但是它的子节点有摄像头

我们 dfs(node,state) 记录在node节点时(以node为根的子树),状态为state下的所有最小摄像头

// 本身有摄像头就看左右孩子了

dfs(node,1) = min(dfs(node->left,1),dfs(node->left,2),dfs(node->left,3)) +

                      min(dfs(node->right,1),dfs(node->right,2),dfs(node->right,3)) + 1

// 本身没有摄像头, 左右孩子不能是2

dfs(node,2) = min(dfs(node->left,1),dfs(node->left,3)) +

                      min(dfs(node->left,1),dfs(node->left,3))

// 本身没有摄像头, 要靠子节点保障,同样左右孩子不能是2,而且至少有一个1

dfs(node,3) = min(dfs(node->left,1)+dfs(root->right,3), dfs(node->left,3)+dfs(node->right,1), 

                       dfs(node->left,1)+dfs(root->right,1))

边界条件怎么思考呢:

        tmp=dfs(nullptr,state)  state为1,tmp是INT_MAX/2  state为2,3,tmp是0

        因为state不应该是1,也就是叶子节点的不应该是用nullptr保障 ,所以我们把这种情况要筛掉

        而当他是2,3时,也就是说让nullptr的监控让他的父节点或者子节点保障,但是因为nullptr不需要监控,所以返回0就行

 代码如下:

/*** 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) {}* };*/
class Solution {
public://最小支配集 int minCameraCover(TreeNode* root) {// 首先对于 一个节点,要被覆盖只有三种情况 //1. 它本身安装了摄像头                  ->记成蓝色 blue 0//2.(他没安装)它的父节点安装了摄像头      ->记成红色 red 1//3.(他没安装)它的孩子有一个安装了摄像头  ->记成黄色 yellow 2//对于根节点是蓝色 ans = min(l_blue,l_red,l_yellow) + min(r_blue,r_red,r_yellow) + 1//对于根节点是红色,子节点不能是红色 ans = min(l_blue,l_yellow) + min(r_blue,r_yellow)//对于根节点是黄色,子节点不能是红色 ans = min(l_blue+r_yellow, l_yellow+r_blue, l_blue+r_blue)map<pair<TreeNode*,int>,int> memo;function<int(TreeNode*,int)> dfs=[&](TreeNode* root,int color)->int{if(!root){if(color==0) return INT_MAX/2;  //else return 0; }if(memo.count({root,color})) return memo[{root,color}];//null节点不能是蓝色 因为叶子节点不能把希望寄托在null上 把这种情况排除//但是null节点可以是红色或者黄色 //红色意味着该null也被监视了,虽然没必要,但是也不算错//黄色意味着该节点的安全由子节点保证 但是本来这个节点就是null 不用保证其安全if(color==0){return memo[{root,color}]=min(dfs(root->left,0),min(dfs(root->left,1),dfs(root->left,2))) + min(dfs(root->right,0),min(dfs(root->right,1),dfs(root->right,2))) + 1;}else if(color==1){return memo[{root,color}]=min(dfs(root->left,0),dfs(root->left,2)) + min(dfs(root->right,0),dfs(root->right,2));}else {return memo[{root,color}]=min(dfs(root->left,0)+dfs(root->right,2),min(dfs(root->left,2)+dfs(root->right,0),dfs(root->left,0)+dfs(root->right,0)));}};return min(dfs(root,0),dfs(root,2));}
};

法二: 贪心

        我们跳出思维定式来看看这个题,怎么 "贪心地" 使得使用最少的节点来支配整个树,显然在一层一层的来看,叶子节点不要放,在叶子节点的父节点放摄像头,然后跳过两个,在这一层放摄像头,然后再跳过两个,在这一层放摄像头,一直这样到根节点. 

        算法的正确可以这样想,叶子节点a一定要被监控,显然放在a的双亲是收益最大的,然后往上找没有监控的节点,用同样的贪心思想

        至于为什么不从根节点往下呢,可以这样想: 叶子节点一定是比根节点要多的,所以应该抓大头

我们把所有节点分成三种情况:

        0. 本身放了摄像头

        1. 本身没有摄像头,但是被子节点监控了

        2. 本身没有摄像头,但是被父节点监控了

这样就是说nullptr往上返回1, (因为显然不会是0,而为了让摄像头最少,又不能是2)

上一层如果收到了下面的两个1,就返回一个2

上一层如果收到了下面的2,就往上返回0 (只要收到一个2)

上一层如果收到了下面的0,就往上返回1 (只要收到一个0)

如果收到了一个0,一个2呢, 显然返回是0, 不如就会有一个节点没有被监控

而最后走到根节点又没有父节点,所有如果根节点返回2, ans是要加1的

/*** 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) {}* };*/
class Solution {
public://最小支配集 int minCameraCover(TreeNode* root) { int res=0;function<int(TreeNode*)> travel=[&](TreeNode*root)->int{if(!root) return 1;int left=travel(root->left);int right=travel(root->right);if(left==1 && right==1) return 2;               //情况1 if(left==2 || right==2) { res++; return 0;}     //情况2if(left==0 || right==0) return 1;               //情况3  return -1;};if(travel(root)==2) res++;return res;}
};

 

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

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

相关文章

蓦然回首,追忆那些备战OCM的日子

蓦然回首 前段时间偶然在墨天轮群看到一位在墨天轮轮社区非常活跃的老兄发的《那些年&#xff0c;我们一起追过的OCP》的文章&#xff0c;获悉墨天轮在举办【我的备考经验】的有奖征文活动&#xff0c;打开那篇文章&#xff0c;一下子又把我的思绪拉回到了好几年前&#xff0c;…

数据结构之顺顺顺——顺序表

1.浅谈数据结构 相信我们对数据结构都不陌生&#xff0c;我们之前学过的数组就是最基础的数据结构&#xff0c;它大概就长这样&#xff1a; 数组 而作为最简单的数据结构&#xff0c;数组只能帮助我们实现储存数据这一个功能&#xff0c;随着学习的深入&#xff0c;和问题的日渐…

React | React.cloneElement 的使用

我看到同事的代码里有 cloneElement&#xff0c;于是去了解了一下这个函数。 就跟它的名字一样&#xff0c;克隆元素&#xff0c;可以基于一个元素创建一个新的元素&#xff0c;并且为新元素添加新的属性或者覆盖已有的属性。 下面是一个简单例子&#xff1a; .node1 {backg…

Java集合框架-Collection-queue

目录 一、Deque二、ArrayDequeArrayDeque层次结构图ArrayDeque概述ArrayDeque底层数据结构ArrayDeque常用方法(简略) 三、PriorityQueuePriorityQueue层次结构图PriorityQueue概述PriorityQueue 底层数据结构PriorityQueue常用方法(详细) Java里有一个叫做Stack的类&#xff0c…

【Linux】进程的控制①之进程创建与进程退出

一 、进程的创建 1、fork函数 fork函数功能&#xff1a;从已经存在的进程中创建一个新进程。新进程为子进程&#xff0c;原进程为父进程。 fork函数创建进程过后&#xff0c;父子进程代码和数据是共享的。在前面也讲过。 2.函数的返回值 如果进程创建成功&#xff0c;给父进…

Linux中的vi与vim:编辑器的王者之争与深度探索

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Linux的起源与发展 2、vi与vim的历史与发展 …

flutter笔记-webrtc使用1:依赖本地包socket.io-client

文章目录 1. 示例工程2. yaml 修改3. 使用4. socketio 关于自定义服务器自定义签名的问题封装成async和await方式 本文开始介绍webrtc的使用&#xff0c;阅读本文的前提是假设你已经使用过webrtc&#xff0c;了解webrtc的交互机制&#xff0c;不了解的可以看之前的文章&#xf…

Python轻量级Web框架Flask(12)—— Flask类视图实现前后端分离

0、前言&#xff1a; 在学习类视图之前要了解前后端分离的概念&#xff0c;相对于之前的模板&#xff0c;前后端分离的模板会去除views文件&#xff0c;添加两个新python文件apis和urls&#xff0c;其中apis是用于传输数据和解析数据 的&#xff0c;urls是用于写模板路径的。 …

数据库介绍(Mysql安装)

前言 工程师再在存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 一、什么是数据库&#xff1f; 文件保存数据有以下几个缺点&#xff1a; 文件的安全性问题文件不利于数据查询和管理文件不利于存储海量数据文件在程序中控制不方便 数据库存储介质&#xff1a; 磁…

【UE C++】设置游戏模式

问题 我们都知道如何使用蓝图创建一个游戏模式并且在这个游戏模式蓝图中去设置“默认pawn类”、“HUD类”、“玩家控制器类”、“游戏状态类”、“玩家状态类”、“旁观者类”。那么如何使用C完成该操作呢&#xff1f; 步骤 1. 首先创建“GameMode”、“GameState”、“HUD”…

Arthas:阿里出品,线上问题快速搞定!

前面我们通过JVM线程分析及内存分析来让大家从服务器资源异常情况下排查代码问题&#xff0c;类似这种的解决方式&#xff0c;更多的是在服务器资源占用已经异常显现&#xff0c;我们就可以按照这种方式去排查和解决。 但实际工作中&#xff0c;可能会出现&#xff1a;接口的TP…

Paddle OCR v4 微调训练文字识别SVTRNet模型实践

文字识别步骤参考&#xff1a;https://github.com/PaddlePaddle/PaddleOCR/blob/main/doc/doc_ch/recognition.md 微调步骤参考:https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7.1/doc/doc_ch/finetune.md 训练必要性 原始模型标点符号和括号容易识别不到 数据…

自动化机器学习:让机器学习更智能

自动化机器学习&#xff1a;让机器学习更智能 在当今数据驱动的时代&#xff0c;机器学习技术已经成为了许多行业和领域的核心。然而&#xff0c;随着数据量的增加和模型复杂度的提升&#xff0c;传统的机器学习方法往往需要大量的人力和时间进行调参和优化&#xff0c;这在某…

3步教你成为微信客户管理高手,助你事半功倍!

在如今的商业世界中&#xff0c;与客户建立良好的关系并提供个性化的服务已成为企业成功的关键。今天就 分享三个简单的步骤&#xff0c;让大家成为微信客户管理的高手&#xff0c;事半功倍&#xff01; 第一步&#xff1a;客户分类与精细化服务 为了更好地管理客户&#xff…

mongodb使用debezium

前置 服务器上需要安装jdk11 jdk下载地址 kafka安装 官网下载地址 安装教程 debezium 安装 运行 Debezium 连接器需要 Java 11 或更高版本 Debezium 并不是一个独立的软件&#xff0c;而是很多个 Kafka 连接器的总称。这些 Kafka 连接器分别对应不同的数据库&#xff0c;…

【C++】C\C++内存管理

下面是围绕C\C内存管理这一块知识谈论相关的内存管理机制&#xff0c;有需要借鉴即可。 同时&#xff0c;我在下面也放了快速建立链表的模板&#xff0c;方便oj题目拿到vs上进行调试。 内存管理目录 1.CPP内存管理1.1new、delete关键字概念1.2特性1.3总结 2.new、delete的底层…

电商API数据采集接口||大数据的发展,带动电子商务产业链,促进了社会的进步

最近几年计算机技术在诸多领域得到了有效的应用&#xff0c;同时在多方面深刻影响着我国经济水平的发展。除此之外&#xff0c;人民群众的日常生活水平也受大数据技术的影响。 主流电商API数据采集接口||在这其中电子商务领域也在大数据技术的支持下&#xff0c;得到了明显的进…

《逃离塔科夫》PVE模式加入付费特别版引发玩家不满

《逃离塔科夫》PVE模式加入付费特别版引发玩家不满 近期&#xff0c;《逃离塔科夫》开发者Battlestate发布了多个新版本&#xff0c;但其中PVE模式只能在价格最高的“Unheard Edition”中购买&#xff0c;导致玩家不满。据悉&#xff0c;“Unheard Edition”售价高达250欧元&a…

Linxu系统服务管理,systemd知识/进程优先级/平均负载/php进程CPU100%怎么解决系列知识!

shell脚本&#xff08;命令&#xff09;放后台 sleep 300& 放到后台运行&#xff0c;脚本或命令要全路径 nohup&#xff1a;用户推出系统进程继续工作 【功能说明】 nohup 命令可以将程序以忽略挂起信号的方式运行起来&#xff0c;被运行程序的输出信息将不会显示到终端 如…

小程序的合同是怎么样写的

​很多商家找第三方做小程序都遭遇到了各种问题&#xff0c;如访问速度慢、服务器关闭、反复收费等。如果当初商家找的是正规的第三方服务商&#xff0c;双方签订了明确的合同条款&#xff0c;出现任何问题后&#xff0c;相信都能够进行解决。下面将具体介绍合同内容&#xff0…