引言

​ 今天的每日一题原题是2643. 一最多的行,直接模拟,切除和最大的一行即可。更换成前几天遇到的更有意思的一题来写这个每日一题。

题目

968. 监控二叉树

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

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

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

示例 1:

  1. 输入:[0,0,null,0,0]
  2. 输出:1
  3. 解释:如图所示,一台摄像头足以监控所有节点。

示例 2:

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

提示:

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

思路

​ 我们要放置最少的摄像头,就要让每个摄像头都可以尽可能多的监控到节点。贪心的看,我们不应该在任何一个叶子节点放置摄像头。原因是,如果有一种最优解是在叶子节点放置摄像头,那么我去掉这个摄像头,放置在这个叶子节点的父节点,监控到的范围会比在叶子节点的摄像头范围更广,明显是更优的做法。

​ 有个上面这个大逻辑,我们可以根据每个节点上有无摄像头、以及有无监控分成3种状态(两两组合是4种,但是不可能出现有摄像头无监控,所以实际上是3种):

  • 0:无摄像头,无监控
  • 1:无摄像头,有监控
  • 2:有摄像头,有监控

对整棵树自下而上来看,根据左右子节点来决策当前节点的状态。

​ 空节点肯定是无摄像头,但是到底有无监控呢?根据我们一开始贪心得到的逻辑,我们不可能在叶子节点放置摄像头,由于空节点可以看到是叶子节点的子节点,所以,我们把空节点状态定义成1:无摄像头,有监控,有利于我们进行递归;

​ 如果左子节点或者右子节点的状态是0:无摄像头,无监控,那么当前节点必须放置摄像头,来监控这个状态为0的子节点,当前节点状态为2:有摄像头,有监控

​ 如果左子节点和右子节点都是1:无摄像头,有监控,那么当前节点不需要放置摄像头,且不会被某个子节点的摄像头监控到,当前节点状态是0:无摄像头,无监控

​ 如果左子节点或者右子节点有摄像头(排除掉某个子节点状态是0,上面已经讨论过了),此时当前节点会被这个子节点的摄像头监控到,当前节点的状态是1:无摄像头,有监控

​ 总结一下,当前节点的2个子节点,每个子节点可能有3种状态,排列后一共可能存在9种情况:

  1. null: cur = 1
  2. left = 0 || right = 0, 5种情况, cur = 2, ans++
  3. left = 1, right = 1, 1种情况, cur = 0
  4. left = 2 || right = 2, 3种情况, cur = 1

图解

代码

  1. private int ans;
  2. /**
  3. * 每个节点可以有3种状态
  4. * 0:无摄像头,无监控
  5. * 1:无摄像头,有监控
  6. * 2:有摄像头,有监控
  7. */
  8. public int minCameraCover(TreeNode root) {
  9. ans = 0;
  10. int rootStatus = postOrder(root);
  11. if (rootStatus == 0) {
  12. // 根节点未被监控,需要在根节点再放1个摄像头
  13. ans++;
  14. }
  15. return ans;
  16. }
  17. private int postOrder(TreeNode node) {
  18. if (node == null) {
  19. // 空节点可以认为是叶子节点的子节点,由于叶子节点状态应该是0(贪心的思路,肯定有1种最佳方案,叶子节点上没有任何摄像头,因为放在叶子节点的父节点,肯定是更好的一个选择),所以空节点的状态,应该是1
  20. return 1;
  21. }
  22. int left = postOrder(node.left);
  23. int right = postOrder(node.right);
  24. if (left == 0 || right == 0) {
  25. ans++;
  26. return 2;
  27. } else if (left == 1 && right == 1) {
  28. return 0;
  29. } else {
  30. return 1;
  31. }
  32. }

耗时

leetcode每日一题:监控二叉树的更多相关文章

  1. 【js】Leetcode每日一题-二叉树的堂兄弟节点

    [js]Leetcode每日一题-二叉树的堂兄弟节点 [题目描述] 在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处. 如果二叉树的两个节点深度相同,但 父节点不 ...

  2. 【JavaScript】Leetcode每日一题-递增顺序搜索树

    [JavaScript]Leetcode每日一题-递增顺序搜索树 [题目描述] 给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没 ...

  3. 【js】Leetcode每日一题-叶子相似的树

    [js]Leetcode每日一题-叶子相似的树 [题目描述] 请考虑一棵二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 . 举个例子,如上图所示,给定一棵叶值序列为 (6, 7 ...

  4. 【js】Leetcode每日一题-制作m束花所需的最少天数

    [js]Leetcode每日一题-制作m束花所需的最少天数 [题目描述] 给你一个整数数组 bloomDay,以及两个整数 m 和 k . 现需要制作 m 束花.制作花束时,需要使用花园中 相邻的 k ...

  5. 【JavaScript】Leetcode每日一题-在D天内送包裹的能力

    [JavaScript]Leetcode每日一题-在D天内送包裹的能力 [题目描述] 传送带上的包裹必须在 D 天内从一个港口运送到另一个港口. 传送带上的第 i 个包裹的重量为 weights[i] ...

  6. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

  7. 【js】Leetcode每日一题-数组异或操作

    [js]Leetcode每日一题-数组异或操作 [题目描述] 给你两个整数,n 和 start . 数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == ...

  8. 【js】Leetcode每日一题-解码异或后数组

    [js]Leetcode每日一题-解码异或后数组 [题目描述] 未知 整数数组 arr 由 n 个非负整数组成. 经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encode ...

  9. 【JavaScript】Leetcode每日一题-青蛙过河

    [JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...

  10. 【JavaScript】Leetcode每日一题-平方数之和

    [JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...

随机推荐

  1. bitset 学习笔记

    引入 顾名思义, \(\texttt{bitset}\) 是用 \(\texttt{bit}\) 组成的 \(\texttt{set}\); 区别于普通的 \(\texttt{bool []}\) 或 ...

  2. JDK8之前日期时间API

    /*java.util.Date类---java.sql.Date类1.两个构造器的使用 >构造器一:Date():创建一个对应当前时间的Date对象 >构造器二:创建指定毫秒数的Date ...

  3. 微信小程序上拉触底事件onReachBottom不触发的解决方案

    1.配置属性问题 //设置容器高度为100% page{ height: 100% } 2. 切换页面时 滚动条滚回到顶部 //切换页面时调用API wx.pageScrollTo({ scrollT ...

  4. ThreeJs-14HTML混合3D渲染

    一.css渲染器基本使用 使用场景:经常在一些3D物体左右还会跟随一些文字等,实际都是标签,应用场景非常广泛 先完成基本的3D,月球围绕地球转,这里就是给月球加了sin函数 然后现在就先创建一个标签体 ...

  5. P10353 [PA2024] Grupa permutacji 题解

    神秘!在这些排列生成的置换群 \(G\) 里,若 \(\exists \pi \in G\) 使得 \(\pi_i=k,\pi_j=l\),则所有这些 \((k,l)\) 被同样数量的 \(\pi\i ...

  6. SCCPC2024 游记

    打了一堆板子,一个都没用上. 队友:zhicheng,nityacke 开场发现 H 是签到,NIT 签了.然后盯 F(圆向某个方向运动,问存不存在一个时刻使得全在长方形之内),发现不外乎一堆二次方程 ...

  7. 在flink消费一段时间kafka后,kafka-group的offset被重置了是怎么回事?

    一.背景 腾讯Flink使用 KafkaSource API创建source端,源码中默认开启了checkpoint的时候提交offset 到kafka-broker.读取kafka数据写入到iceb ...

  8. 为什么TCP需要三次握手?深入解析背后的设计哲学

    在互联网通信中,TCP(传输控制协议)是确保数据可靠传输的基石.而TCP连接的建立过程--"三次握手"(Three-Way Handshake),看似简单的三个步骤,却蕴含了网络协 ...

  9. Paxos算法:如何解决分布式系统中的共识问题?

    背景 Paxos 算法是 Leslie Lamport(莱斯利·兰伯特)在 1990 年提出了一种分布式系统 共识 算法.这也是第一个被证明完备的共识算法(前提是不存在拜占庭将军问题,也就是没有恶意节 ...

  10. Ubuntu详细的安装和配置ssh教程

    Ubuntu安装和配置ssh的步骤如下: 打开终端,输入以下命令安装ssh: sudo apt-get install openssh-server 安装完成后,启动ssh服务: sudo syste ...