代码随想录day37 | 贪心算法P6 | ● 738 ● 968 ● 总结

738.单调递增的数字 

当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

思路

首先想到暴力法,超时

暴力(超时)

class Solution {public int monotoneIncreasingDigits(int n) {if(judge(n)){return n;}else{for(int i = n-1; i > 0; i--){if(judge(i)){return i;}}}return 0;}public boolean judge(int n){String s = String.valueOf(n);char [] c = s.toCharArray();for(int i=1; i < c.length; i++){if(c[i] >= c[i-1]){continue;}else{return false;}}return true;}
}

贪心

贪心策略;拿一个两位的数字来举例。

例如:98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。

然后判断遍历方向,从前往后还是从后往前。

从前往后会出现如下问题:

如332:变化如下 332 -> 329 -> 将第二个3 -- 变为2 导致它小于第一个3了。

这是因为从前往后没用到上次比较得出的结果,从后往前:332 -> 329 -> 299

class Solution {public int monotoneIncreasingDigits(int n) {if(judge(n)){return n;}else{String s = String.valueOf(n);char [] c = s.toCharArray();int start = 0;for(int i = c.length - 1; i > 0; i--){if(c[i-1] > c[i]){c[i-1] = (char)(c[i-1] - 1);start = i;}}for(int i = start; i<c.length; i++){c[i] = '9';}return Integer.parseInt(String.valueOf(c));}}public boolean judge(int n){String s = String.valueOf(n);char [] c = s.toCharArray();for(int i=1; i < c.length; i++){if(c[i] >= c[i-1]){continue;}else{return false;}}return true;}
}

总结

本题只要想清楚个例,例如98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]减一,strNum[i]赋值9,这样这个整数就是89。就可以很自然想到对应的贪心解法了。

想到了贪心,还要考虑遍历顺序,只有从后向前遍历才能重复利用上次比较的结果。

最后代码实现的时候,也需要一些技巧,例如用一个flag来标记从哪里开始赋值9。

968.监控二叉树 

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

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

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

示例 1:

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

示例 2:

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

思路

首先明确 如何放置摄像头才能让总体数量最小:

可以发现,示例中的摄像头都没有放在叶子节点上,摄像头可以覆盖上中下三层,如果放在叶子节点上就会浪费一层,所以应当把摄像头放在叶子节点的父节点位置。

那么为什么不从头节点开始看,而是从叶子节点看呢?头节点不放 只能省下一个,而叶子节点不放,省下的摄像头是指数级别的。

所以,从下往上看,局部最优:让叶子节点的父节点安放摄像头,所用摄像头最少,整体最优:全部摄像头最少。

此时,大概思路:从下往上,先给叶子节点的父节点安放摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。

那么剩下两个难点:

        1、二叉树从下往上遍历

        2、如何隔两个节点放一个摄像头

1:后序遍历,左右中,并且因为需要搜索整棵树,采用递归函数搜索整棵树的写法。

2:利用状态转移的公式。记录三种状态,0-无覆盖,1-有摄像头,2-有覆盖。

首先 空节点只能是有覆盖状态,因为:为了让摄像头数量最少,我们要尽量让叶子节点的父节点安装摄像头,这样才能摄像头的数量最少。那么空节点不能是无覆盖的状态,这样叶子节点就要放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。

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

递归后序遍历,终止条件即为遇到空节点,同时返回状态值 2 有覆盖

然后利用递归搜索整棵树的模板,定义代表左右子树状态值的int数 left right,进行后序遍历、

单层递归逻辑:

有如下四类情况:(三种状态,0-无覆盖,1-有摄像头,2-有覆盖。)

①当left为2 right也为2时,此时root应返回 0 无覆盖

②当left right至少有一个为 0 无覆盖时,此时root返回 1 有摄像头

③当left right 至少有一个为1 有摄像头时,此时root返回 2 有覆盖

④当根节点 状态为 0 res++;

注意上述顺序种 ③中的部分逻辑 如(1,0)左节点有摄像头,右节点无覆盖

提前在②中 处理,因为需满足所有节点被覆盖。

 代码

class Solution {public int res = 0;public int minCameraCover(TreeNode root) {//根节点无覆盖,此时需在根节点加一个if(tracing(root) == 0) {res++;}return res;}/*0 无覆盖1 有摄像头2 有覆盖*/public int tracing(TreeNode root){//空结点,默认有覆盖if(root == null) return 2;int left = tracing((root.left));int right = tracing(root.right);//左右状态共九种//左右都有覆盖,此时节点为无覆盖if(left == 2 &&  right == 2){//(2,2)return 0;}else//左右至少有一个是无覆盖的,那么应该返回1,在此节点处放摄像头if(left == 0 || right == 0){// (0,0) (0,1) (0,2) (1,0) (2,0)// 状态值为 1 摄像头数 ++;res++;return 1;}else{//左右至少有一个是有摄像头的,此时节点为有覆盖//(1,1) (1,2) (2,1)return 2;}}
}

总结

贪心思路:局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!

求解:后序遍历整棵树 + 状态转移 + 单层递归情况分解

贪心总结 

首先贴一个图: 来自代码随想录 (programmercarl.com)

开始复习以往做过的题目,计划通过类似方式对做过的题目进行总结归纳。 

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

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

相关文章

012:vue结合纯CSS实现蛇形流程图/步骤条

文章目录 1. 实现效果2. 实现代码 1. 实现效果 2. 实现代码 <template><div class"container"><div v-for"(item, index) in list" class"grid-item"><div class"step">step{{index1}}</div></div&…

MySQL - 深入MySQL索引的秘密(一)

1. 如果没有任何索引,数据库是如何根据查询语句搜索数据的? 在磁盘文件中,数据页之间是组成双向链表的,然后数据页内部的数据行是组成单向链表的,而且数据行是根据主键从小到大排序的。然后每个数据页里都会有一个页目录,里面根据数据行的主键存放了一个目录,同时数据行…

新版HI3559AV100开发注意事项(三)

新版HI3559AV100开发注意事项&#xff08;三&#xff09; 十九、用的sdk是Hi3559V200_MobileCam_SDK_V1.0.1.5 播放AAC音频文件&#xff0c;adec->ao;adec的初始化里面包括了aaclc解码器的注册&#xff0c;可是在HI_MPI_ADEC_RegisterDecoder(&s32Handle, &stAac);…

【漏洞复现】OpenMetadata 命令执行漏洞复现(CVE-2024-28255)

声明&#xff1a;亲爱的读者&#xff0c;我们诚挚地提醒您&#xff0c;Aniya网络安全的技术文章仅供个人研究学习参考。任何因传播或利用本实验室提供的信息而造成的直接或间接后果及损失&#xff0c;均由使用者自行承担责任。Aniya网络安全及作者对此概不负责。如有侵权&#…

类和对象中阶1⃣️-默认成员函数(构造函数 析构函数)

目录 1.类的6个默认成员函数 2.构造函数 2.1 概念 3.析构函数 3.1 概念 3.2 特性 1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成…

JavaThread线程

目录 程序--进程--线程 程序&#xff1a; 进程&#xff1a; 线程&#xff1a; 进程和线程的关系 创建线程 单线程模式 代码 图解 运行 代码 运行 创建线程 方式一 代码 运行 方式二 代码 运行 总结&#xff1a; Thread类中常用的方法 1、 代码 运行…

电脑剪切复制到u盘文件丢失怎么办?未备份者的应急指南

在日常生活和工作中&#xff0c;我们经常使用电脑和U盘进行文件的传输和备份。然而&#xff0c;在剪切复制文件到U盘的过程中&#xff0c;有时可能会遇到文件丢失或无法找到的问题&#xff0c;而这时又没有备份&#xff0c;这无疑让人头疼不已。那么&#xff0c;面对这种情况&a…

java的aop实现方式

java的aop可以通过三种方式来实现 1.使用ajc编译的插件来完成增强 这种方法会直接修改编译完成的class文件&#xff0c;不需要依赖springboot 2.动态代理proxy 2.1cglib 可以代理接口&#xff0c;方法等&#xff0c;这种方式代理类是目标类的子类&#xff0c;要求目标类不…

使用 EFCore 和 PostgreSQL 实现向量存储及检索

随着 ChatGPT 的兴起及其背后的 AIGC 产业不断升温,向量数据库已成为备受业界瞩目的领域。FAISS、Milvus、Pinecone、Chroma、Qdrant 等产品层出不穷。市场调研公司 MarketsandMarkets 的数据显示,全球向量数据库市场规模预计将从 2020 年的 3.2 亿美元增长至 2025 年的 10.5…

Ps 滤镜:风格化

风格化 Stylize滤镜通过置换像素和通过查找并增加图像的对比度&#xff0c;基于原图像生成绘画或印象派的效果。 查找边缘 Find Edges “查找边缘”滤镜通过分析图像的色彩和亮度变化来识别边缘。 这种处理方式使得图像的主要轮廓以一种艺术化的线条形式被强调出来&#xff0c;…

大语言模型的指令调优:综述

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文标题&#xff1a;Instruction Tuning for Large Language Models: A Survey 论文地址&#xff1a;https://arxiv.org/abs/2308.10792 指令调优是提升大语言模型&#xff08;LLMs&#xff09;性能…

python爬虫3-xpath批量定位元素的方法

以爬取豆瓣影评的电影名称为例。 第一步 鼠标右键单击&#xff0c;选择【检查】 第二步 切换到【元素】标签&#xff0c;展示源代码 选择下图的小箭头&#xff0c;再选择想要定位的文本&#xff0c;源代码会自动定位到该文本。 第三步 鼠标放在该文本的源代码上&#xff0c;…

Pytorch官方FlashAttention速度测试

在Pytorch的2.2版本更新文档中&#xff0c;官方重点强调了通过实现FlashAtteneion-v2实现了对scaled_dot_product_attention约2X左右的加速。 今天抽空亲自试了下&#xff0c;看看加速效果是否如官方所说。测试前需要将Pytorch的版本更新到2.2及以上&#xff0c;下面是测试代码…

Prometheus-Grafana基础篇安装绘图

首先Prometheus安装 1、下载 https://prometheus.io/download/ 官网路径可以去这儿下载 2、如图&#xff1a; 3.解压&#xff1a; tar -xf prometheus-2.6.1.linux-amd64 cd prometheus-2.6.1.linux-amd64 4.配置文件说明&#xff1a; vim prometheus.yml 5.启动Promethe…

kail渗透工具之nmap的使用方法

准备工作&#xff1a;开启两台虚拟机和一台Windows主机 kail Linux攻击机&#xff1a;192.168.80.131 red hat靶机&#xff1a;192.168.80.129 Windows主机&#xff1a;192.168.252.42 1、nmap扫描工具的简介 nmap是用来探测计算机网络上的主机和服务的一种安全扫描器。为了绘…

2024年视频号小店无货源,你一定要尝试一下,出九单收入1W+

大家好&#xff0c;我是电商花花。 如果说去年视频号的流量还差点意思&#xff0c;那么今年的视频号销量一定是非常高的&#xff0c;随着视频号的扩展&#xff0c;也让更多的创业者和博主入驻视频号&#xff0c;让更多人了解到了视频号小店&#xff0c;是这样赚钱的。 首先&am…

深水采样器小口径特氟龙材质FEP贝勒管

FEP贝勒管&#xff0c;深水采样器(bailers tube)&#xff0c;是一种经济型便携式水质采样器&#xff0c;操作简单&#xff0c;使用方便&#xff0c;性价比高&#xff0c;能大限度的保证样品的真实性。采样管直径很小&#xff0c;能够采取小口径的深水井水样。是一款简单实用&am…

磁盘管理显示u盘无媒体怎么恢复数据

随着科技的发展&#xff0c;U盘已成为我们日常生活和工作中不可或缺的数据存储工具。然而&#xff0c;当我们在使用U盘时&#xff0c;有时会遇到“磁盘管理显示U盘无媒体”的困扰。面对这一问题&#xff0c;许多用户可能会感到惊慌失措&#xff0c;担心数据丢失。本文将为您详细…

c语言例题,计算1/1-1/2+1/3-1/4+1/5……+1/99-1/100的值,打印结果

例题&#xff1a;计算分式1/1-1/21/3-1/41/5……1/99-1/100的值&#xff0c;打印结果 根据题目&#xff0c;我们知道需要计算的是一个固定值&#xff0c; 先定义三个变量来当作分式里的三个值&#xff0c;变量i当作分式里的分母部分&#xff0c;通过for循环来实现分母每次循环…

存储器层次结构

内存 对于内存已经不像曾经那般陌生了&#xff0c;在汇编中&#xff0c;我们大量接触了内存&#xff0c;但是我们还没有对它有个确切、深入的了解。 内存其实叫做随机访问存储器&#xff08;RAM&#xff0c;Random Access Memory&#xff09;&#xff0c;最基本的存储单位称为…