当前位置: 首页 > news >正文

代码随想录算法训练营第37天 | ● 738.单调递增的数字 ● 968.监控二叉树 ● 总结

文章目录

  • 前言
  • 一、738.单调递增的数字
  • 二、968.监控二叉树
  • 总结

前言

可以吗?


一、738.单调递增的数字

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

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

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

下面代码的flag为start,flag是为了标识使得后面变为9的位置,防止1000得出900的操作(正确:999),亦或是234得出199(正确:234)。

1和2相同,只是更改了length()与length,以及start--->flag;

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

二、968.监控二叉树

从题目中示例,其实可以得到启发,我们发现题目示例中的摄像头都没有放在叶子节点上!这是很重要的一个线索,摄像头可以覆盖上中下三层,如果把摄像头放在叶子节点上,就浪费的一层的覆盖。所以把摄像头放在叶子节点的父节点位置,才能充分利用摄像头的覆盖面积。那么有同学可能问了,为什么不从头结点开始看起呢,为啥要从叶子节点看呢?

因为头结点放不放摄像头也就省下一个摄像头, 叶子节点放不放摄像头省下了的摄像头数量是指数阶别的。所以我们要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!局部最优推出全局最优,找不出反例,那么就按照贪心来!

此时,大体思路就是从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。此时这道题目还有两个难点:

  1. 二叉树的遍历
  2. 如何隔两个节点放一个摄像头

有如下三种:

  • 该节点无覆盖
  • 本节点有摄像头
  • 本节点有覆盖

我们分别有三个数字来表示:

  • 0:该节点无覆盖
  • 1:本节点有摄像头
  • 2:本节点有覆盖

大家应该找不出第四个节点的状态了。

一些同学可能会想有没有第四种状态:本节点无摄像头,其实无摄像头就是 无覆盖 或者 有覆盖的状态,所以一共还是三个状态。

因为在遍历树的过程中,就会遇到空节点,那么问题来了,空节点究竟是哪一种状态呢? 空节点表示无覆盖? 表示有摄像头?还是有覆盖呢?

空节点不能是无覆盖的状态,这样叶子节点就要放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。

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

本题的难点首先是要想到贪心的思路,然后就是遍历和状态推导。

在二叉树上进行状态推导,其实难度就上了一个台阶了,需要对二叉树的操作非常娴熟。

/**
     节点的状态值:
       0 表示无覆盖
       1 表示 有摄像头
       2 表示有覆盖
    后序遍历,根据左右节点的情况,来判读 自己的状态
     */

// 如果左右节点都覆盖了的话, 那么本节点的状态就应该是无覆盖,没有摄像头 (2,2)

// 左右节点都是无覆盖状态,那 根节点此时应该放一个摄像头, (0,0) (0,1) (0,2) (1,0) (2,0),状态值为 1,摄像头数 ++;

// 左右节点的 状态为 (1,1) (1,2) (2,1) 也就是左右节点至少存在 1个摄像头,那么本节点就是处于被覆盖状态

class Solution {int  res=0;public int minCameraCover(TreeNode root) {// 对根节点的状态做检验,防止根节点是无覆盖状态 .if(minCame(root)==0){res++;}return res;}/**节点的状态值:0 表示无覆盖1 表示 有摄像头2 表示有覆盖后序遍历,根据左右节点的情况,来判读 自己的状态*/public int minCame(TreeNode root){if(root==null){// 空节点默认为 有覆盖状态,避免在叶子节点上放摄像头return 2;}int left=minCame(root.left);int  right=minCame(root.right);// 如果左右节点都覆盖了的话, 那么本节点的状态就应该是无覆盖,没有摄像头if(left==2&&right==2){//(2,2)return 0;}else 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) 也就是左右节点至少存在 1个摄像头,// 那么本节点就是处于被覆盖状态return 2;}}
}


总结

我们可以的!

只要一路坚持下来,不仅基础扎实,而且进步也是飞速的。

http://www.lryc.cn/news/148189.html

相关文章:

  • SOPC之NIOS Ⅱ实现电机转速PID控制(调用中断函数)
  • ElasticSearch安装为Win11服务
  • ransac拟合平面,代替open3d的segment_plane
  • Docker技术--Docker镜像管理
  • 生态环境保护3D数字展厅提供了一个线上环保知识学习平台
  • OPENCV实现计算描述子
  • Android View动画之LayoutAnimation的使用
  • 低代码与低代码平台的概念解析
  • 玩转Mysql系列 - 第8篇:详解排序和分页(order by limit),及存在的坑
  • Django实现音乐网站 ⒂
  • 爬虫逆向实战(二十八)--某税网第一步登录
  • 【Dots之003】SystemAPI.Query相关基础笔记
  • vue v-for 例子
  • 206.Flink(一):flink概述,flink集群搭建,flink中执行任务,单节点、yarn运行模式,三种部署模式的具体实现
  • 科技探究之旅--亲子研学活动
  • 华为云Stack的学习(三)
  • 大数据平台三大优势详解-行云管家
  • 智慧景区方案:AI与视频融合技术如何助力景区监管智能化升级?
  • HTML基础--Form表单--内联元素
  • 【月度刷题计划同款】常规状压 DP 启发式搜索
  • C#: Json序列化和反序列化,集合为什么多出来一些元素?
  • Docker教程-centos快速安装和配置Docker
  • three.js(四):react + three.js
  • IDEA全局统一设置Maven
  • CSS中的margin与padding
  • 匿名内部类、Lambda、方法引用 的总结
  • 本地docker registry 搭建
  • 阿里云将关停代销业务
  • 【ES6】JavaScript的Proxy:理解并实现高级代理功能
  • [Pandas] 求百分比并添加百分(%)号