【算法】二分查找(下)
一、山峰数组的峰顶索引
题目链接:852. 山脉数组的峰顶索引 - 力扣(LeetCode)
题目描述:
给定一个长度为
n的整数 山脉 数组arr,其中的值递增到一个 峰值元素 然后递减。返回峰值元素的下标。
你必须设计并实现时间复杂度为
O(log(n))的解决方案。示例 1:
输入:arr = [0,1,0] 输出:1示例 2:
输入:arr = [0,2,1,0] 输出:1示例 3:
输入:arr = [0,10,5,2] 输出:1提示:
3 <= arr.length <= 10^50 <= arr[i] <= 10^6- 题目数据 保证
arr是一个山脉数组
题目分析:
我们只需要在一个 先升序后降序的数组中 找到转折点的下标即可
需要注意的是,在【提示】中,明确说明:该数组的长度是大于等于3的,并且保证了数组arr是一个山脉数组(满足先升序后降序--必有转折点)。所以当数组长度为3时,返回值为1.
所以峰值元素肯定不会出现在数组的两端,而是出现在数组中间。
即返回值区间为:[1,arr.length-2]
题目所满足的条件在后续解题中,有很大的作用
在本题中,数组具有【二段性】,即当数组被分为两个部分后,每个部分内部都有某种特定的性质。在本题中,前半部分满足升序,后半部分满足降序。我们在【手撕二分查找】中的二分查找本质中,说过:当数组具有有序性/二段性时,存在一个分界点时,使得分界点前后元素的性质不同,便可以使用二分查找来解决问题。
解题思路:
在循环中,我们只需要判断mid处元素是否大于mid-1处的元素,然后依此更新左右边界,直到找到峰值元素
1.确认区间形式:【左开右闭】
2.维护区间形式:初始值、循环条件、左右边界
初始值:left=0,right=arr.length-2/arr.length-1(由于峰值元素不出现在数组两端,搜索区间为[1,arr.length-2])。注意:left一定不能为-1,因为当left=-1时,可能会导致mid-1<0越界
循环条件:left<right
左右边界:left=mid,right=mid-1
3.选择mid的计算方式:向上调整:mid=left+(right-left+1)/2
4.返回值:return left
如果我们用left=-1去提交,发现会报一个越界异常,如下:

arr=[3,5,3,2,0]
越界的原因:
- 初始时:left= -1,right=4。mid=2,arr[mid]=3<arr[mid-1]=5。令right=mid-1=1
- 此时:left=-1,right=1。mid=0。由于mid-1=-1<0,所以越界
为了避免越界,要保证mid-1>=0,即mid>=1。
初始化left=0则可以解决这一问题
解题代码:
class Solution {public static int peakIndexInMountainArray(int[] arr) {int left=0;int right=arr.length-2;//或者可以为arr.length-1while(left<right){int mid=left+(right-left+1)/2;if(arr[mid]>arr[mid-1])left=mid;else right=mid-1;}return left;}
} 二、寻找峰值
1.题目链接:162. 寻找峰值 - 力扣(LeetCode)
2.题目描述:
峰值元素是指其值严格⼤于左右相邻值的元素。给你⼀个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何⼀个峰值 所在位置即可。你可以假设 nums[-1] = nums[n] = -∞ 。你必须实现时间复杂度为 O(log n) 的算法来解决此问题。⽰例 1:输⼊:nums = [1,2,3,1]输出:2解释:3 是峰值元素,你的函数应该返回其索引 2。⽰例 2:输⼊:nums = [1,2,1,3,5,6,4]输出:1 或 5解释:你的函数可以返回索引 1,其峰值元素为 2;或者返回索引 5, 其峰值元素为 6。提⽰:1 <= nums.length <= 1000-2^31 <= nums[i] <= 2^31 - 1对于所有有效的 i 都有 nums[i] != nums[i + 1]
题目分析:
首先解析为什么给出nums[-1]=nums[n]= -∞
这保证了数组一定有峰值。
比如数组是严格递增的,那么nums[n-1]就是峰值。为什么?因为此时nums[n-2]<nums[n-1]>nums[n]。同样地,假如数组是严格递减的,那么nums[0]就是峰值。因为此时nums[-1]<nums[0]>nums[1]
其实简单来说,峰值元素就是一个大于其两侧的元素而已。而nums[-1]和nums[n]为 -∞,则保证了下标为0或者n-1处的元素也可能是峰值元素。
定理:如果i<n-1且nums[i-1]<nums[i],那么在下标[i,n-1]中一定存在至少一个峰值
反证法:假设下标[i,n-1]中没有峰值
·由于i处不是峰值且nums[i-1]<nums[i],所以一定有nums[i]<nums[i+1]成立,否则i就是峰值了。
·由于i+1处不是峰值且nums[i]<nums[i+1],所以一定有nums[i+1]<nums[i+2]成立,否则i+1就是峰值了。
·依此类推,得 nums[i-1]<nums[i]<nums[i+1]<nums[i+2]<........nums[n-1]>nums[n]= -∞
这意味着nums[n-1]是峰值,假设不成立,所以定理成立。
同理可得,如果i<n-1且nums[i-1]>nums[i],那么在[0,i-1]中一定存在至少一个峰值
解题思路:
根据上述分析,我们已知数组中一定存在至少一个峰值。只需要通过比较nums[i-1]和nums[i]得大小关系,从而不断地缩小峰值所在位置的范围,二分找到峰值即可
细节:
- 当数组只有一个元素时,该元素即为峰值。应当返回下标0
- 当n-1处的元素为峰值元素时,每次更新的都是left,当left走到n-1处(right初始值)时,结束循环,返回n-1
我们这里选择【左开右闭】来解决本题
由于当数组只有一个元素时,应该返回下标0。所以这里初始化left=0
解题代码:
class Solution {public int findPeakElement(int[] nums) {int left=0;int right=nums.length-1;//左开右闭 (0,n-1]while(left<right){int mid=left+(right-left+1)/2;if(nums[mid]>nums[mid-1])left=mid;else right=mid-1;}return left;}
} 三、搜索旋转排序数组中的最小值
1.题目链接:153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)
2.题目描述:
已知一个长度为
n的数组,预先按照升序排列,经由1到n次 旋转 后,得到输入数组。例如,原数组nums = [0,1,2,4,5,6,7]在变化后可能得到:
- 若旋转
4次,则可以得到[4,5,6,7,0,1,2]- 若旋转
7次,则可以得到[0,1,2,4,5,6,7]注意,数组
[a[0], a[1], a[2], ..., a[n-1]]旋转一次 的结果为数组[a[n-1], a[0], a[1], a[2], ..., a[n-2]]。给你一个元素值 互不相同 的数组
nums,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。你必须设计一个时间复杂度为
O(log n)的算法解决此问题。示例 1:
输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。示例 3:
输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。提示:
n == nums.length1 <= n <= 5000-5000 <= nums[i] <= 5000nums中的所有整数 互不相同nums原来是一个升序排序的数组,并进行了1至n次旋转
题目分析:
其实本题的数组可以看成由 两段升序数组(假设为数组M、N)拼接而成。
如果原数组由N+M拼接而成,那么M+N就是一个升序数组。而M、N分别又是升序的
我们用一张图表示,会更加清晰

其中C点就是我们所要求的点
二分的本质:找到一个判断标准,使得查找区间能够一分为二
通过图像我们发现,[A,B]区间内的点都是严格大于D点的值,C点的值是严格小于D点的值。但是当[C,D]区间只有一个元素的时候,C点的值可能等于D点的值
因此,初始化左右两个指针left,right:
根据mid的落点,我们可以这样划分下一次查询的区间:
·当mid在[A,B]区间的时候,也就是mid位置的值严格大于D点的值,下一次查询区间在[mid+1,right]
·当mid在[C,D]区间的时候,也就是mid位置的值严格小于等于D点的值,下一次查询区间在[left,mid]
当区间长度变成1的时候,就是我们要找的结果
注意:我们这里的D需要额外处理。我们将查询区间内的最后一个元素看作D。
解题代码:
class Solution {public static int findMin(int[] nums) {//左闭右开int left=0;int right=nums.length-1;int x=nums[right];//标记一下最后一个位置的值while(left<right){int mid=left+(right-left)/2 ;if(nums[mid]>x)left=mid+1;else right=mid;}return nums[left];}
} 四、0~n-1中缺失的数字
1.题目链接:LCR 173. 点名 - 力扣(LeetCode)
2.题目描述:
某班级 n 位同学的学号为 0 ~ n-1。点名结果记录于升序数组
records。假定仅有一位同学缺席,请返回他的学号。示例 1:
输入:records = [0,1,2,3,5] 输出:4示例 2:
输入:records = [0, 1, 2, 3, 4, 5, 6, 8] 输出:7提示:
1 <= records.length <= 10000
简单来说:有一个长度为n的升序数组,数组内的元素应该为0~n-1。请找出缺少的那个数字
我们本题使用【左闭右开】来解题
这题其实更加简单了。我们只需要比较下标是否与元素相等即可。
如果相等,表示左侧没有缺少,右侧缺少,那么下一次查询区间为[mid+1,right]
如果不相等,表示左侧缺少,右侧不缺少,那么下一次查询区间为[left,mid]
左右指针相遇处的元素则表示 下标与元素不相等。返回此处下标--表示缺少元素
解题代码:
class Solution {public static int takeAttendance(int[] records) {int left=0;int right=records.length;//左闭右开while(left<right){int mid=left+(right-left)/2;if(records[mid]==mid)left=mid+1;else right=mid;}return left;}
}
相关文章:
【算法】二分查找(下)
一、山峰数组的峰顶索引 题目链接:852. 山脉数组的峰顶索引 - 力扣(LeetCode) 题目描述: 给定一个长度为 n 的整数 山脉 数组 arr ,其中的值递增到一个 峰值元素 然后递减。 返回峰值元素的下标。 你必须设计并实现时…...
【动手学深度学习】#6 卷积神经网络
主要参考学习资料: 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 由于本系列一开始跳过了第一章引言部分,因此系列编号比书本章节编号提前。现改为和书本统一(因为之前自己的原始笔记也是按照书本章节编…...
认识一家公司:瑞芯微(Rockchip Electronics Co., Ltd.)以及旗下的两款芯片RK3288\RK3588
瑞芯微(Rockchip Electronics Co., Ltd.)简介 一、公司概况 瑞芯微电子股份有限公司(简称“瑞芯微”)成立于2001年,总部位于中国福建省福州市,是一家专注于集成电路设计与研发的高新技术企业。公司采用Fa…...
爬虫面试题
总结一下最近面试遇到的笔试题 1、解释Python中的init方法的作用。 在Python中,__init__方法是一种特殊的构造方法,主要用于在创建类的实例时初始化对象。至少接受至少一个参数:self,它是对当前实例的引用,可以通过添加其他参数…...
Netty——零拷贝
文章目录 1. 什么是零拷贝?2. 为什么需要零拷贝?2.1 传统 I/O 的拷贝流程2.2 零拷贝的优化2.2.1 通过 sendfile 系统调用2.2.2 通过 mmap (内存映射) 系统调用 3. Netty 实现零拷贝的方式3.1 文件传输优化:FileRegion 封装3.2 直接内存 (Dire…...
Java制作简单的聊天室(复习)
设计的知识点:几乎包含java基础的全部知识点(java基础语法,java基础进阶:双列集合,io流,多线程,网络编程等) 代码如下 客户端: 服务器采用的时多线程的循环多线程的方式…...
ES 字段的映射定义了字段的类型及其行为
在 Elasticsearch 中,字段的映射定义了字段的类型及其行为。你提供的 content_answer 字段映射如下: Json 深色版本 "content_answer": { "type": "text", "fields": { "keyword": { …...
Android开发点击字符串web链接跳到系统浏览器上
Android开发点击字符串web链接跳到系统浏览器上 直接上代码:用到你就拿去用 public static void performItemUrlClick(View view, String contentUrl) {if (!TextUtils.isEmpty(contentUrl)) {Intent intent new Intent();if (!contentUrl.startsWith("http…...
运维规则之总结(Summary of Operation and Maintenance Rules)
运维规则之总结 在运维领域,经验和流程往往决定了系统的稳定性与可靠性。一个运维人,总结出了以下10条运维规则,涵盖了从基础管理到高级策略的全面内容,旨在帮助运维人员更好地应对各种挑战,确保系统的平稳运行。 1.…...
智能家居赋能宠物经济:未来宠物行业的另一片蓝海
一、引言:宠物经济的范式转移 随着城市化进程的加速,宠物在现代家庭中的地位日益重要,宠物经济蓬勃发展。近年来,智能家居技术的兴起为宠物行业带来了新的变革,从传统的情感消费模式向技术赋能的精细化养宠模式转变。…...
C++Primer学习(13.6 对象移动)
13.6 对象移动 新标准的一个最主要的特性是可以移动而非拷贝对象的能力。如我们在13.1.1节(第440页)中所见,很多情况下都会发生对象拷贝。在其中某些情况下,对象拷贝后就立即被销毁了。在这些情况下,移动而非拷贝对象会大幅度提升性能。 如我…...
RHCE工程师特训指南
RHCE(红帽认证工程师)是Linux领域极具含金量的认证之一,其考试以实操为主,注重系统管理、网络服务配置及自动化运维能力。以下内容可帮助对RHCE考生高效规划学习路径。 一、RHCE认证概述 认证结构 RHCE认证分为两部分ÿ…...
内核、进程和线程---操作系统
操作系统 操作系统位于用户程序和硬件之间,通过系统调用提供接口可以让应用程序去使用硬件,但是硬件资源的管理和安全控制由操作系统负责。 用户空间和内存空间 在计算机系统中,内存可以分为两大区域:内核空间(Ker…...
如何在 Postman 中上传图片并在请求中正确引用?
Postman 是一款常用的 API 测试工具,它不仅可以测试 API 的请求和响应,还支持多种数据格式包括图片。如何在 Postman 中传输图片? Postman 如何上传图片并在请求中使用教程...
平板实现 adb connect 连接的步骤
1. 检查设备的开发者选项 确保平板设备已开启开发者模式,并启用了USB调试。 2. 检查设备和电脑的网络连接 确保平板和电脑连接到同一个Wi-Fi网络,确认设备的 IP 地址是否正确。 通过 ping 命令测试: ping 192.168.3.243. 通过USB线进行初…...
安全+低碳+高效:Acrel-3000助力企业打造未来型电能管理体系-安科瑞黄安南
一 背景 电能因为方便传输、易于转换、便于控制等特性,成为广大企事业单位生产、办公最主要的能量来源。双碳背景下,由于电能清洁、高效、零排放的特点,能源消费侧将逐步以电代煤、以电代油、以电代气,形成以电为中心的能源消费体…...
专注自习室:番茄工作法实践
专注自习室:番茄工作法实践 我需要一个任务管理工具,但在网上找了很多都找不到合适的工具。市面上的大多数产品过于强调任务完成性,给我带来了很强的心理压力,这种压力最终反而降低了我的工作效率。于是我决定自己动手࿰…...
docker save如何迁移镜像更节省空间?
文章目录 方法一:使用docker save命令方法二:直接保存多个镜像到一个tar文件哪个方法更节省磁盘空间?空间效率对比实际测试示例其他优势结论 如何用脚本迁移加载镜像 迁移镜像时候,往往会碰到基础镜像相同的很多镜像需要迁移&…...
LeetCode算法题(Go语言实现)_16
题目 给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …...
CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案
计算机该如何求解三角函数?或许你的第一印象是采用泰勒展开,或者采用多项式进行逼近。对于前者,来回的迭代计算开销成本很大;对于后者,多项式式逼近在较窄的范围內比较接近,超过一定范围后,就变…...
JVM 面经
1、什么是 JVM? JVM 就是 Java 虚拟机,它是 Java 实现跨平台的基石。程序运行之前,需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件;程序运行时,JVM 会对字节码文件进行逐行解释,翻译成机器码指令&#x…...
SEO(搜索引擎优化)详解
SEO(搜索引擎优化)详解 SEO是Search Engine Optimization的缩写,中文称为"搜索引擎优化"。它是指通过一系列技术和方法,提高网站在搜索引擎自然(非付费)搜索结果中的排名,从而获得更…...
Ubuntu平台下安装Node相关环境
说明:在进行VUE、TS等开发需要用到NodeJS相关环境,不同的项目有时候需要不同的Node版本支撑。本文将详细讲解NVM、Node、Yarn、PM2等环境安装的实施步骤。 测试服务器环境:22.04 LTS。 1. NVM 定义:Node Version Manager&#x…...
deepseek大模型一体机与deepseek的关系
deepseek大模型一体机与deepseek的关系 一、deepseek大模型一体机是什么 DeepSeek大模型一体机是由深度求索(DeepSeek)公司推出的软硬件一体化AI解决方案,旨在为企业提供高效、便捷的大模型部署和应用能力。 二、deepseek大模型一体机与de…...
Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站
开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组,开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App,登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…...
高等数学-第七版-上册 选做记录 习题7-2
1. 2....
基于Promise链式调用的多层级请求性能优化
代码优化-循环嵌套关联请求 1. 背景 在实际开发中,我们经常会遇到需要嵌套关联请求的场景,比如: 获取项目列表获取项目详情获取项目进度 2. 问题 在这种场景下,我们可能会遇到以下问题: 串行请求瀑布流ÿ…...
【强化学习】基于深度强化学习的微能源网能量管理与优化策略研究【Python】
目录 主要内容 程序要点 2.1 微能源网系统组成 2.2 强化学习及Q学习算法 部分代码 运行结果 下载链接 主要内容 该程序借助深度 Q 网络(DQN),学习预测负荷、风 / 光可再生能源功率输出及分时电价等环境信息,运用…...
楼宇自控借何种技术,驱动建筑迈向高效绿色
在全球积极倡导可持续发展的大背景下,建筑行业作为能源消耗和碳排放的大户,实现高效绿色发展迫在眉睫。楼宇自控系统凭借其先进的技术手段,成为推动建筑向高效绿色转型的关键力量。那么,楼宇自控究竟借助哪些技术,让建…...
监控易一体化运维:监控易机房管理,打造高效智能机房
在数字化浪潮中,企业对数据中心和机房的依赖程度与日俱增,机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁,见证了机房管理从传统模式向智能化、精细化转变的过程。今天,就为大家深度剖析监控易在机房管理方面的卓越表现…...
