代码随想录-Day37

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
在这里插入图片描述

方法一:

/**
时间复杂度 : O(NlogN) 排序需要O(NlogN)
空间复杂度 : O(logN)  java 的内置排序是快速排序 需要 O(logN)空间*/
class Solution {public int[][] merge(int[][] intervals) {List<int[]> res = new LinkedList<>();//按照左边界排序Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));//initial start 是最小左边界int start = intervals[0][0];int rightmostRightBound = intervals[0][1];for (int i = 1; i < intervals.length; i++) {//如果左边界大于最大右边界if (intervals[i][0] > rightmostRightBound) {//加入区间 并且更新startres.add(new int[]{start, rightmostRightBound});start = intervals[i][0];rightmostRightBound = intervals[i][1];} else {//更新最大右边界rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]);}}res.add(new int[]{start, rightmostRightBound});return res.toArray(new int[res.size()][]);}
}

这段Java代码实现了一个函数 merge,用于合并一系列有重叠的区间。给定一个二维数组 intervals,其中每个 intervals[i] 是一个长度为2的数组,表示一个区间 [start, end],该函数的目标是将这些区间合并成一个新的区间数组,使得在新数组中任意两个区间没有交集,并且覆盖所有原始区间。以下是代码的详细解析:

时间复杂度和空间复杂度说明

  • 时间复杂度:O(NlogN),主要来自对区间按左边界排序的操作,其中N是区间数量。
  • 空间复杂度:O(logN),这是由于Java内置排序方法(快速排序)的递归调用栈空间。

代码解析

  1. 初始化:创建一个名为 resLinkedList 用于存储不重叠的合并后的区间。同时,初始化 start 为数组中第一个区间的起始位置,rightmostRightBound 为当前已知的最远的右边界。

  2. 排序:使用 Arrays.sort() 方法按区间的左边界升序排序整个 intervals 数组。排序是本算法的关键步骤,它确保了后续遍历过程中的合并逻辑简单且有效。

  3. 遍历并合并

    • 遍历排序后的区间数组。对于每个区间,如果当前区间的起始位置大于已知的最远右边界,说明当前区间与之前处理过的所有区间都不重叠,可以将前一个区间的结束位置与 start 组成的区间加入结果列表 res,并更新 start 为当前区间的起始位置,同时更新 rightmostRightBound 为当前区间的结束位置。
    • 如果当前区间起始位置不大于最远右边界,说明当前区间与前一个区间有重叠,此时只需要更新 rightmostRightBound 为当前区间和已知最远右边界中的较大值,以覆盖更大的范围。
  4. 添加最后一个区间:遍历结束后,别忘了将最后一个有效区间 [start, rightmostRightBound] 添加到结果列表 res 中。

  5. 转换并返回结果:最后,将 res 中的数据转换成数组类型并返回。

示例说明

假设输入区间为 [[1,3],[2,6],[8,10],[15,18]],经过排序、遍历合并后,最终的不重叠区间数组将是 [[1,6],[8,10],[15,18]],这正是函数预期输出的结果。

// 版本2
class Solution {public int[][] merge(int[][] intervals) {LinkedList<int[]> res = new LinkedList<>();Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));res.add(intervals[0]);for (int i = 1; i < intervals.length; i++) {if (intervals[i][0] <= res.getLast()[1]) {int start = res.getLast()[0];int end = Math.max(intervals[i][1], res.getLast()[1]);res.removeLast();res.add(new int[]{start, end});}else {res.add(intervals[i]);}         }return res.toArray(new int[res.size()][]);}
}

这个Java代码是用于解决“合并区间”问题的另一个版本实现。给定一个二维数组 intervals,其中每个 intervals[i] 为一个长度为2的数组,表示一个区间 [start, end],该函数的目标是将所有重叠的区间合并成一个新的区间数组,并且在新数组中任意两个区间不会有重叠部分。下面是该代码的详细解析:

代码解析

  1. 初始化:定义一个 LinkedList<int[]> res 作为结果容器来存储合并后的区间。使用 Arrays.sort() 方法对输入区间按起始位置升序排序,便于后续处理。

  2. 添加首个区间:将排序后的首个区间直接加入结果列表 res

  3. 遍历合并:从第二个区间开始遍历整个 intervals 数组。对于每个区间,执行以下操作:

    • 判断重叠:如果当前区间的起始位置 intervals[i][0] 小于等于结果列表中最后一个区间的结束位置 res.getLast()[1],说明这两个区间有重叠。
    • 合并区间:当发现重叠时,合并这两个区间。新的起始位置取两者中较小的(在这里直接取了 res.getLast()[0],因为当前区间起始位置肯定不会小于已加入的区间的起始位置),新的结束位置取两者结束位置的较大值。然后从 res 中移除旧的最后一个区间,添加合并后的新区间。
    • 无重叠则直接添加:如果当前区间与结果列表最后一个区间无重叠,则直接将当前区间加入到结果列表 res 中。
  4. 转换并返回结果:遍历结束后,将 LinkedList 类型的结果列表转换为数组类型并返回。

时间复杂度和空间复杂度

  • 时间复杂度:O(NlogN),其中N为区间数量。排序操作占主导地位。
  • 空间复杂度:O(N),res 用于存储不重叠的合并区间,最坏情况下需要与输入区间相同的空间。

示例说明

例如,给定输入区间 [[1,3],[2,6],[8,10],[15,18]],经过处理后,合并后的区间应为 [[1,6],[8,10],[15,18]],这正是该函数预期返回的结果。

738. 单调递增的数字

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

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

示例 1:

输入: n = 10
输出: 9
示例 2:

输入: n = 1234
输出: 1234
示例 3:

输入: n = 332
输出: 299

方法一:

版本1
class Solution {public int monotoneIncreasingDigits(int N) {String[] strings = (N + "").split("");int start = strings.length;for (int i = strings.length - 1; i > 0; i--) {if (Integer.parseInt(strings[i]) < Integer.parseInt(strings[i - 1])) {strings[i - 1] = (Integer.parseInt(strings[i - 1]) - 1) + "";start = i;}}for (int i = start; i < strings.length; i++) {strings[i] = "9";}return Integer.parseInt(String.join("",strings));}
}

这段Java代码是为了解决一个问题:给定一个非负整数N,找到具有单调递增数字的最大的数,其数字重新排列后小于或等于N。单调递增数字是指每个位置上的数字都不小于其左侧的数字(从左到右)。

代码解析

  1. 字符串转换:首先,将整数N转换成字符串数组strings,方便单独处理每一位数字。

  2. 从右向左扫描:使用一个外层循环从字符串的末尾开始向前遍历(索引istrings.length - 10),目的是检测数字是否递减。如果当前位的数字小于前一位的数字(strings[i] < strings[i - 1]),则:

    • 将前一位的数字减一((Integer.parseInt(strings[i - 1]) - 1)),并将其转换回字符串形式。
    • 记录这个位置start = i,作为后续处理的起点,因为start右侧的所有数字都需要变成9以确保结果是最大的单调递增数字。
  3. 填充9:使用一个内层循环,从位置start到字符串的末尾,将所有这些位置的数字替换为"9",以确保生成的数字尽可能大。

  4. 转换回整数并返回:最后,使用String.join("", strings)将修改后的字符串数组连接成一个字符串,再通过Integer.parseInt(...)将其转换回整数并返回。

示例

例如,如果N = 332,经过处理后的字符串数组变为["3", "2", "9"],重新组合并转换回整数得到329,这是小于等于332的最大单调递增数字。

注意:这个解法在处理边界情况(如当N本身就是单调递增或需要大幅度减少首位数字时)表现良好,但在某些情况下可能不是最高效的算法,特别是在N非常大,且大部分数字都需要减少时。

方法二:

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

这个版本的代码实现与第一个版本非常相似,主要的不同在于细节处理和变量命名上,逻辑本质上是一致的。下面是这个版本的解析:

代码解析

  1. 转换为字符数组:首先,将整数n转换为字符串s,然后进一步转换成字符数组chars。这样可以直接操作每一位数字,无需频繁地在数字和字符串之间转换。

  2. 从右向左扫描:外层循环的起始点调整为i = s.length() - 2,这是因为现在是从倒数第二位开始比较(避免数组越界,同时正确定位需要检查的相邻数字对)。如果发现chars[i]大于chars[i + 1],说明违反了递增顺序:

    • chars[i]减一,表示这一位不能保持原值,需要生成更小的递增序列。
    • 更新start = i + 1,记录接下来应该全部填充为9的起始位置。
  3. 填充9:与之前版本相同,从位置start到字符串的末尾,所有这些位置的字符都被替换为字符’9’。

  4. 转换回整数并返回:最后,使用String.valueOf(chars)将字符数组转换回字符串,然后通过Integer.parseInt(...)转换为整数并返回结果。

优化点

  • 直接在字符数组上操作减少了字符串到数字、数字到字符串的转换次数,这可能在处理大数值时略微提高效率。
  • 循环起始点的调整去掉了对数组长度的减一操作,使得逻辑更直观。

示例

假设n = 332,处理过程与第一个版本相同,最终得到的字符数组表示的数字为329,转换为整数后返回。

此算法同样适用于寻找给定整数N下,最大的单调不减(即递增)整数。

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

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

相关文章

安装react之nvm版本低引起的问题

1.背景 准备搭建一个react&#xff0c;然后看官网文档 创建项目&#xff0c;使用命令行 npx create-next-applatest 创建项目的流程都是正常的。当我准备运行项目的时候&#xff0c;报错了 原先的报错没有了&#xff0c;从网上找了一个类似的 重要的内容是&#xff1a;当前…

网络技术原理需要解决的5个问题

解决世界上任意两台设备时如何通讯的&#xff1f;&#xff1f; 第一个问题&#xff0c;pc1和pc3是怎么通讯的&#xff1f; 这俩属于同一个网段&#xff0c;那么同网段的是怎么通讯的&#xff1f; pc1和pc2属于不同的网段&#xff0c;第二个问题&#xff0c;不同网段的设备是…

【5】apollo编写python节点步骤及实例

在workspace/modules下新建包buildtool create --template component modules/test_one 编译包 buildtool build -p modules/test_two/ 增加自己的proto消息 在刚才自动生成的proto文件里面添加自己定义的消息,记得重新编译. syntax "proto2";package apollo;…

UltraEditUEStudio软件安装包下载及安装教程

​根据软件大数据显示提供预定义的或使用者创建的编辑“环境”&#xff0c;能记住 UltraEdit 的所有可停靠窗口、工具栏等的状态。实际上我们可以这样讲HTML 工具栏&#xff0c;对常用的 HTML 功能作了预配置;文件加密/解密;多字节和集成的 IME。根据使用者情况表明Git Editor&…

vue3项目使用Electron打包成exe的方法与打包报错解决

将vue3项目打包成exe文件方法 一、安装 1.安装electron npm install electron --save-devnpm install electron-builder --save-dev 2.在vue项目根目录新建文件index.js // index.js// Modules to control application life and create native browser window const { app…

font-spider按需生成字体文件

font-spider可以全局安装,也可以单个项目内安装,使用npm run xxxx的形式 npm i font-spider "dev": "font-spider ./*.html" <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&…

什么是APP分发-了解APP分发的核心概念

APP分发的定义和意义 大家有没有过这样的经历&#xff1a;辛辛苦苦开发了一款APP&#xff0c;却不知道该怎么让更多人知道和使用&#xff1f;APP分发的重要性就凸显出来了。APP分发就是将你的应用推送到不同的应用市场和平台&#xff0c;让更多用户能够下载和使用。 小猪app封…

[机器学习算法]支持向量机

支持向量机&#xff08;SVM&#xff09;是一种用于分类和回归分析的监督学习模型。SVM通过找到一个超平面来将数据点分开&#xff0c;从而实现分类。 1. 理解基本概念和理论&#xff1a; 超平面&#xff08;Hyperplane&#xff09;&#xff1a;在高维空间中&#xff0c;将数据…

【Python机器学习】k均值聚类——k均值的失败案例

k均值可能不总能找到“正确”的簇个数&#xff0c;每个簇仅由其中心定义&#xff0c;这意味着每个簇都是凸形。因此&#xff0c;k均值只能找到相对简单的形状。k均值还假设所有簇在某种程度上具有相同的“直径”&#xff0c;它总是将簇之间的边界刚好画在簇中心的之间位置。有时…

python使用pywebview打造一个现代化的可视化GUI界面

&#x1f308;所属专栏&#xff1a;【python】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的…

海洋生物识别系统+图像识别+Python+人工智能课设+深度学习+卷积神经网络算法+TensorFlow

一、介绍 海洋生物识别系统。以Python作为主要编程语言&#xff0c;通过TensorFlow搭建ResNet50卷积神经网络算法&#xff0c;通过对22种常见的海洋生物&#xff08;‘蛤蜊’, ‘珊瑚’, ‘螃蟹’, ‘海豚’, ‘鳗鱼’, ‘水母’, ‘龙虾’, ‘海蛞蝓’, ‘章鱼’, ‘水獭’, …

Linux配置中文环境

文章目录 前言中文语言包中文输入法中文字体 前言 在Linux系统中修改为中文环境&#xff0c;通常涉及以下几个步骤&#xff1a; 中文语言包 更新源列表&#xff1a; 更新系统的软件源列表和语言环境设置&#xff0c;确保可以安装所需的语言包。 sudo apt update sudo apt ins…

《计算机英语》 Unit 3 Software Engineering 软件工程

Section A Software Engineering Methodologies 软件工程方法论 Software development is an engineering process. 软件开发是一个工程过程。 The goal of researchers in software engineering is to find principles that guide the software development process and lea…

如何选择服务器?快解析能搭建私人服务器吗?

随着网络的发展&#xff0c;搭建私人服务器逐渐成为网络达人们的热门选择&#xff0c;比如建立私人性质的博客、论坛、FTP、个人网站、服务器集群等。通过源搭建私人服务器&#xff0c;就可以将很多资源分享到网络上进行信息共享。随之而来的是服务器市场不断扩大&#xff0c;在…

网络安全:Web 安全 面试题.(XSS)

网络安全&#xff1a;Web 安全 面试题.&#xff08;XSS&#xff09; 网络安全面试是指在招聘过程中,面试官会针对应聘者的网络安全相关知识和技能进行评估和考察。这种面试通常包括以下几个方面&#xff1a; &#xff08;1&#xff09;基础知识:包括网络基础知识、操作系统知…

# Kafka_深入探秘者(1):初识 kafka

Kafka_深入探秘者&#xff08;1&#xff09;&#xff1a;初识 kafka 一、kafka 特性 1、Kafka &#xff1a;最初是由 Linkedln 公司采用 Scala 语言开发的一个多分区、多副本并且基于 ZooKeeper 协调的分布式消息系统&#xff0c;现在已经捐献给了 Apache 基金会。目前 Kafka…

CentOS系统查看版本的各个命令

cat /etc/centos-release 查看CentOS版本 uname -a 命令的结果分别代表&#xff1a;当前系统的内核名称、主机名、内核发型版本、节点名、系统时间、硬件名称、硬件平台、处理器类型以及操作系统名称 cat /proc/version 命令用于查看Linux内核的版本信息。执行该命令后&#xf…

【Linux基础】SSH登录

SSH简介 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。 SSH通过在网络中建立安全隧道来实现SSH客户端与服务器之间的连接。 SSH最常见的用途是远程登…

为什么用excel求出的和是错误的?

Excel中求和结果错误的原因可能有几种常见的情况&#xff1a;1. **数据格式问题**&#xff1a;有时候数字可能被错误地视为文本格式。这种情况下&#xff0c;Excel 在求和时会忽略这些单元格。你可以通过将这些单元格的格式改为数值格式来解决。2. **隐藏的行或列**&#xff1a…

Java程序之动物声音“模拟器”

题目&#xff1a; 设计一个“动物模拟器”&#xff0c;希望模拟器可以模拟许多动物的叫声和行为&#xff0c;要求如下&#xff1a; 编写接口Animal&#xff0c;该接口有两个抽象方法cry()和getAnimalName()&#xff0c;即要求实现该接口的各种具体的动物类给出自己的叫声和种类…