LeetCode刷题日记之贪心算法(五)

目录

  • 前言
  • 无重叠区间
  • 划分字母区间
  • 合并区间
  • 单调递增的数字
  • 监控二叉树
  • 总结


前言

随着对贪心算法的不断深入,本篇文章将继续挑战一些经典的题目,进一步巩固这一算法的应用技巧。希望博主记录的内容能够帮助大家更好地掌握贪心算法的解题思路✍✍✍


无重叠区间

LeetCode题目链接

这道题就是给一个区间集合,然后让我们尽可能少地移除掉区间使得剩下的区间互不重叠

请添加图片描述

我们来思路梳理

  • 我们可以先将每个区间的结束时间进行升序排序。这是因为希望保留结束时间早的区间,尽可能减少与后续区间的重叠🤔🤔🤔然后遍历排序后的区间,依次选择区间。每次选择时检查当前区间的起始时间是否大于等于前一个选择的区间的结束时间。如果是,则说明这两个区间不重叠;否则,就需要移除当前区间🤓🤓🤓在遍历过程中,记录不重叠的区间数量,最后用总区间数减去不重叠区间数即可得到最少需要移除的区间数量😀😀😀

很清楚的逻辑了,完整代码如下

class Solution {public int eraseOverlapIntervals(int[][] intervals) {//防止整数溢出方法排序Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1]));int prevEnd = intervals[0][1]; //初始化前序区间结束时间int removals = 0;//初始化需要移除区间的数量for(int i = 1; i < intervals.length; i++){if(intervals[i][0] < prevEnd){ //如果有重叠removals++;}else{prevEnd = intervals[i][1];//更新状态}}return removals;}
}

划分字母区间

LeetCode题目链接

这道题就是说要尽可能划分多的字符串片段,每个字符串片段中的字母不会有重叠

请添加图片描述

我们来思路梳理

  • 首先我们遍历字符串,记录每个字符在字符串中的最后出现位置🤔🤔🤔 然后我们开始从字符串的开头进行遍历,逐步扩展当前片段的结束位置。对于每个字符,我们将当前片段的结束位置更新为该字符的最后出现位置。如果当前遍历到的字符位置等于当前片段的结束位置,说明这个片段已经可以划分完毕🤓🤓🤓 当一个片段完成后,记录该片段的长度,继续从下一个字符开始划分新的片段,直到遍历完字符串😀😀😀

也是很清楚的逻辑了,完整代码如下

class Solution {public List<Integer> partitionLabels(String s) {//记录小写字符的最后出现位置int[] lastOccurrence = new int[26];for(int i = 0; i < s.length(); i++){lastOccurrence[s.charAt(i) - 'a'] = i;}List<Integer> result = new ArrayList<>();int start = 0;//初始片段起始位置int end = 0;//初始片段结束位置for(int i = 0; i < s.length(); i++){end = Math.max(end, lastOccurrence[s.charAt(i) - 'a']); //取遍历到的字符最后位置为片段结束位置if(i == end){//遍历到片段的结束位置result.add(end - start + 1);start = i + 1; //更新下一片段的起始位置}}return result;}
}

合并区间

LeetCode题目链接

这道题和无重叠区间题目类似,但是不是移除重叠区间而是合并重叠区间,使得合并后的区间不重叠,但这里的话就是区间相连也视作重叠区间要合并🤔🤔🤔

请添加图片描述

我们来思路梳理

  • 将区间按照起始位置进行升序排序。这样可以保证处理时区间是从左到右有序的,方便合并重叠的区间🤔🤔🤔然后遍历排序后的区间,维护一个合并后的区间列表。如果当前区间的起始位置小于等于前一个合并区间的结束位置,说明它们重叠,则更新当前合并区间的结束位置为两个区间中较大的结束位置;否则,将当前区间加入合并后的结果列表😀😀😀

这道题的逻辑也比较清楚,完整代码如下

class Solution {public int[][] merge(int[][] intervals) {//按照区间起始位置安全排序Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));//使用链表存储合并后的区间LinkedList<int[]> merged = new LinkedList<>();for(int[] interval : intervals){//如果 merged 为空或当前区间与前一个区间不重叠,直接添加if(merged.isEmpty() || merged.getLast()[1] < interval[0]){merged.add(interval);}else{//合并当前区间和前一个区间,更新结束位置merged.getLast()[1] = Math.max(merged.getLast()[1], interval[1]);}}//将链表转换为二维数组返回return merged.toArray(new int[merged.size()][]);}
}

可能会有所疑问的部分

  • 这里用链表来存储和普通数组列表有什么区间呢?🤔🤔🤔
    • 因为这里是一个不断添加删除和删除的场景,需要频繁地插入新的区间,LinkedList在插入操作上比ArrayList更高效,在列表处理的时候根据频繁访问还是频繁插入选择合适的列表数据结构😀😀😀

单调递增的数字

LeetCode题目链接

这道题就是返回一个小于或等于整数n的最大单增数,所谓的单调递增数是指从左至右相邻数xy满足x<=y

请添加图片描述

我们来思路梳理

  • 最优解是要找到小于或等于 n 的最大单调递增数字。我们需要从右往左扫描数字,找到第一个不满足单调递增的地方,从那个地方开始进行调整🤔🤔🤔 从右往左检查,如果发现某一位数字比下一位大,就将该位减 1,同时将它右边所有的数字变成 9,以保证数字尽可能大且是单调递增的😀😀😀

思路梳理的很清楚了,完整代码如下

class Solution {public int monotoneIncreasingDigits(int n) {//将数字转换为字符数组方便进行逐位操作char[] num = Integer.toString(n).toCharArray();int length = num.length;//从右往左遍历,找到不满足单调递增的地方int maker = length;for(int i = length - 1; i > 0; i--){if(num[i] < num[i - 1]){num[i - 1]--;maker = i;//标记不满足单调递增的地方,后面要变成9}}//将标记后的所有数字设置为9for(int i = maker; i < length; i++){num[i] = '9';}return Integer.parseInt(new String(num));}
}

可能存在的不易理解的问题

  • 为什么只需要找一次 marker 并把后面数字变为 9🤔🤔🤔
  • 这是因为当我们发现某个位置的数字不满足单调递增时,我们贪心地把前一位数字减 1,然后从这一位的后面所有数字全部变成 9,这样可以确保得到的数字尽可能大,且保持单调递增。如果在某一位减 1 后的调整仍然不满足单调递增,继续扫描之前的数字并进行调整即可。关键是,所有发生问题的数字调整后,其后的部分都应该变为 9,这样我们只需要在扫描过程中标记一次 marker,并统一将后面的数字变为 9😀😀😀

监控二叉树

LeetCode题目链接

就是给个二叉树,然后的话给二叉树中的一个节点安装摄像头,这个摄像头可以监控节点自身、父节点和子节点要求返回监控整个二叉树的最少摄像头数量

请添加图片描述

我们来思路梳理

  • 这道题可以通过贪心算法结合后序遍历来解决🤔🤔🤔 为了确保用最少的摄像头覆盖所有节点,我们优先从叶子节点开始考虑放置摄像头。如果某个节点的子节点尚未被覆盖,那么我们必须在该节点放置摄像头。通过后序遍历自底向上进行,确保每次都能局部最优地选择摄像头位置😀😀😀 使用后序遍历的方式,从叶子节点开始遍历,递归地决定是否在当前节点放置摄像头。这样可以确保每个节点和它的子节点都能被覆盖

逻辑梳理的比较清楚了,完整代码如下

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {private static final int NOT_COVERED = 0;//节点未被覆盖private static final int COVERD_NO_CAMERA = 1;//节点被覆盖但没有摄像头private static final int HAS_CAMERA = 2;//节点安装了摄像头private int cameraCount = 0;//记录安装摄像头的数量public int minCameraCover(TreeNode root) {// 如果根节点未被覆盖,则在根节点安装摄像头if (dfs(root) == NOT_COVERED) {cameraCount++;}return cameraCount;}private int dfs(TreeNode root){if(root == null) return COVERD_NO_CAMERA;//空节点视为已覆盖int left = dfs(root.left);int right = dfs(root.right);//如果左或右子节点未被覆盖,则当前节点需要安装摄像头if(left == NOT_COVERED || right == NOT_COVERED){cameraCount++;return HAS_CAMERA;}//如果任意子节点有摄像头,则当前节点已被覆盖,无需安装摄像头if(left == HAS_CAMERA || right == HAS_CAMERA){return COVERD_NO_CAMERA;}//如果子节点都被覆盖但没有摄像头,则当前节点未被覆盖return NOT_COVERED;}
}

可能不易理解的地方

  • 为什么要单独处理根节点?🤔🤔🤔
    • 这里因为我们的贪心逻辑是根据父节点来覆盖子节点,而根节点没有父节点,无法通过父节点来被覆盖,所以需要单独检查根节点是否已经被覆盖。如果根节点未被覆盖,我们需要在根节点上放置一个摄像头😀😀😀

总结

贪心算法的第一轮记录就到这里了,后续博主将开始动态规划这一问题的记录分享,大家一起加油✊✊✊

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

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

相关文章

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中&#xff0c;Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃&#xff0c;Kubernetes 尝试重启该容器&#xff0c;但由于持续崩溃&#xff0c;重启的间隔时间逐渐增加。下面将详细介绍 CrashLoopBackOff 状态的原因、解决方案及相关命令的输出解释。 …

Openlayers高级交互(3/20):动态添加 layer 到 layerGroup,并动态删除

layerGroup 是 OpenLayers 库中的一个类,用于创建图层组。图层组允许您将多个图层组合在一起,并作为一个整体来控制它们的可见性和其他属性。本示例动态添加layer到layerGroup,并动态删除。 效果图 专栏名称内容介绍Openlayers基础实战 (72篇)专栏提供73篇文章,为小白群…

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序 文章目录 一、基本原理一、基本概念二、原理和流程1. 数据准备2. 模型构建3. 灰狼优化算法设计4. 模型训练与优化5. 模型评估与预测 三、优势与应用四、总结 二、实验结…

Docker 用例:15 种最常见的 Docker 使用方法

容器化应用程序而不是将它们托管在虚拟机上是过去几年一直流行的概念&#xff0c;使容器管理流行起来。Docker 处于这一转变的核心&#xff0c;帮助组织无缝地采用容器化技术。最近&#xff0c;Docker 用例遍布所有行业&#xff0c;无论规模大小和性质如何。 什么是Docker&…

Windows--使用node.js的免安装版本

原文网址&#xff1a;Windows--使用node.js的免安装版本_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows下如何使用node.js的免安装版本。 下载 1.访问官网 https://nodejs.org/en 记住这个版本号&#xff0c;这个是长期支持的版本。 2.找到压缩包 点击其他下载&#…

windows系统中,在cmd窗口演练 Redis 基本操作命令

文章目录 一、Redis 介绍1.1 Redis 的应用场景1.2 Redis 的特点 二、Windows版Redis安装三、Redis Desktop Manager安装四、Redis 常用基本操作4.1 查看操作4.2 操作string类型的命令4.2.1 设置获取Key4.2.2 MSET&#xff08;Multi&#xff09;支持批量设置key、MGET支持批量获…

平时使用Xshell能连接虚拟机,现在突然连接不上

问题&#xff1a;平时使用Xshell能连接虚拟机&#xff0c;现在突然连接不上&#xff0c;使用ip addr 命令查看ip地址 ens33 接口状态为 DOWN&#xff0c;没有分配IP地址&#xff0c;这通常意味着该网络接口未激活或存在配置问题。&#xff08;因为平时能连接&#xff0c;就说明…

DNS代理是什么?浅析DNS代理的工作原理及应用

DNS代理作为计算机网络中重要的一环&#xff0c;扮演着连接用户和互联网服务的关键角色。来了解DNS代理的定义、功能、工作原理以及在网络中的应用场景和重要性吧。 一、理解DNS代理。 DNS代理充当在用户和真正的DNS服务器之间的中介。它接收来自用户端的DNS查询请求&#xf…

std::function和bind绑定器

本文来自《深入应用C11 代码优化与工程级应用》 std::function和std::bind&#xff0c;使我们使用标准库函数时更加方便&#xff0c;且还能方便地实现延迟求值。 1.可调用对象(Callable Objects) 可调用对象有如下几种定义&#xff1a; (1)是一个函数指针 #include<ios…

php elasticsearch/elasticsearch使用apikey访问接口

此处使用的windows版es和kibana。 1.前提&#xff1a;以安装好es和kibana并正常运行&#xff0c;记得保存es安装完成时提示的账号密码。 2.登录kibana,创建索引并加入几条数据,可以通过kibana界面添加或者通过调用接口添加&#xff0c;非重点不赘述了。 3.添加ApiKey, 使用…

Linux 部署 Harbor 镜像仓库详解

文章目录 安装 Docker安装 Harbor访问 Harbor 安装 Docker 本次部署流程使用的是1台阿里云ECS&#xff0c;Ubuntu 22.04&#xff0c;2核4G。 首先需要做的是在当前服务器上&#xff0c;安装好 Docker&#xff0c;参考链接如下&#xff1a; https://blog.csdn.net/weixin_4659…

ESD防静电闸机如何保护汽车电子产品

随着汽车电子技术的快速发展&#xff0c;汽车中集成了越来越多的电子设备&#xff0c;如车载信息娱乐系统、自动驾驶传感器、驾驶辅助系统等。静电放电可能导致电子组件的损坏、性能下降&#xff0c;甚至使整个系统失效。因此&#xff0c;如何有效保护汽车电子产品免受静电损害…

【【自动驾驶】车辆运动学模型】

【自动驾驶】车辆运动学模型 1. 引言2. 以车辆重心为中心的单车模型2.1 模型介绍2.2 滑移角 β \beta β 的推导2.2 航向角 ψ \psi ψ推导过程&#xff1a;2.3 滑移角 β \beta β2.3 Python代码实现2.4 C代码实现 3. 前轮驱动的单车模型3.1 模型介绍3.3 Python代码实现3.4 …

软件I2C的代码

I2C的函数 GPIO的配置——scl和sda都配置为开漏输出 void MyI2C_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruture;GPIO_InitStruture.GPIO_Mode GPIO_Mode_Out_OD;GPIO_InitStruture.GPIO_PinGPIO_Pin_10 | GPIO_Pin_…

Debug-029-el-table实现自动滚动分批请求数据

前情提要 最近做了一个小优化&#xff0c;还是关于展示大屏方面的。大屏中使用el-table展示列表数据&#xff0c;最初的方案是将数据全部返回&#xff0c;确实随着数据变多有性能问题&#xff0c;有时请求时间比较长。这里做的优化就是实现列表的滚动到距离底部一定高度时再次请…

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…

项目实战:Qt+OpenCV仿射变换工具v1.1.0(支持打开图片、输出棋盘角点、调整偏移点、导出变换后的图等等)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/143105881 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…

python中frida的安装+frida-server(雷电模拟器)保姆级安装教程

一.安装雷电模拟器 雷电模拟器官网 直接下载安装即可 &#xff08;1&#xff09;打开必要权限 雷电模拟器的设置已完毕 二.安装adb工具 本文以autox.js来实现adb操作 &#xff08;1&#xff09;vscode中下载auto.js插件 &#xff08;2&#xff09;雷电模拟器下载autox.j…

【大模型实战篇】大模型分词算法Unigram及代码示例

1. 算法原理介绍 与 BPE 分词&#xff08;参考《BPE原理及代码示例》&#xff09;和 WordPiece 分词&#xff08;参考《WordPiece原理及代码示例》&#xff09;不同&#xff0c;Unigram 分词方法【1】是从一个包含足够多字符串或词元的初始集合开始&#xff0c;迭代地删除其中的…

Spring Boot Druid 数据库连接池入门

1. Druid 单数据源 1.1 引入依赖 在 pom.xml 文件中&#xff0c;引入相关依赖。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…