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

【算法】二分查找(下)

一、山峰数组的峰顶索引

题目链接: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^5
  • 0 <= 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]

越界的原因:

  1. 初始时:left= -1,right=4。mid=2,arr[mid]=3<arr[mid-1]=5。令right=mid-1=1
  2. 此时: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]得大小关系,从而不断地缩小峰值所在位置的范围,二分找到峰值即可

细节:

  1. 当数组只有一个元素时,该元素即为峰值。应当返回下标0
  2. 当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.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 中的所有整数 互不相同
  • 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;}
}

相关文章:

【算法】二分查找(下)

一、山峰数组的峰顶索引 题目链接&#xff1a;852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个长度为 n 的整数 山脉 数组 arr &#xff0c;其中的值递增到一个 峰值元素 然后递减。 返回峰值元素的下标。 你必须设计并实现时…...

【动手学深度学习】#6 卷积神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 由于本系列一开始跳过了第一章引言部分&#xff0c;因此系列编号比书本章节编号提前。现改为和书本统一&#xff08;因为之前自己的原始笔记也是按照书本章节编…...

认识一家公司:瑞芯微(Rockchip Electronics Co., Ltd.)以及旗下的两款芯片RK3288\RK3588

瑞芯微&#xff08;Rockchip Electronics Co., Ltd.&#xff09;简介 一、公司概况 瑞芯微电子股份有限公司&#xff08;简称“瑞芯微”&#xff09;成立于2001年&#xff0c;总部位于中国福建省福州市&#xff0c;是一家专注于集成电路设计与研发的高新技术企业。公司采用Fa…...

爬虫面试题

总结一下最近面试遇到的笔试题 1、解释Python中的init方法的作用。 在Python中&#xff0c;__init__方法是一种特殊的构造方法&#xff0c;主要用于在创建类的实例时初始化对象。至少接受至少一个参数&#xff1a;self,它是对当前实例的引用&#xff0c;可以通过添加其他参数…...

Netty——零拷贝

文章目录 1. 什么是零拷贝&#xff1f;2. 为什么需要零拷贝&#xff1f;2.1 传统 I/O 的拷贝流程2.2 零拷贝的优化2.2.1 通过 sendfile 系统调用2.2.2 通过 mmap (内存映射) 系统调用 3. Netty 实现零拷贝的方式3.1 文件传输优化&#xff1a;FileRegion 封装3.2 直接内存 (Dire…...

Java制作简单的聊天室(复习)

设计的知识点&#xff1a;几乎包含java基础的全部知识点&#xff08;java基础语法&#xff0c;java基础进阶&#xff1a;双列集合&#xff0c;io流&#xff0c;多线程&#xff0c;网络编程等&#xff09; 代码如下 客户端&#xff1a; 服务器采用的时多线程的循环多线程的方式…...

ES 字段的映射定义了字段的类型及其行为

在 Elasticsearch 中&#xff0c;字段的映射定义了字段的类型及其行为。你提供的 content_answer 字段映射如下&#xff1a; Json 深色版本 "content_answer": { "type": "text", "fields": { "keyword": { …...

Android开发点击字符串web链接跳到系统浏览器上

Android开发点击字符串web链接跳到系统浏览器上 直接上代码&#xff1a;用到你就拿去用 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)

运维规则之总结 在运维领域&#xff0c;经验和流程往往决定了系统的稳定性与可靠性。一个运维人&#xff0c;总结出了以下10条运维规则&#xff0c;涵盖了从基础管理到高级策略的全面内容&#xff0c;旨在帮助运维人员更好地应对各种挑战&#xff0c;确保系统的平稳运行。 1.…...

智能家居赋能宠物经济:未来宠物行业的另一片蓝海

一、引言&#xff1a;宠物经济的范式转移 随着城市化进程的加速&#xff0c;宠物在现代家庭中的地位日益重要&#xff0c;宠物经济蓬勃发展。近年来&#xff0c;智能家居技术的兴起为宠物行业带来了新的变革&#xff0c;从传统的情感消费模式向技术赋能的精细化养宠模式转变。…...

C++Primer学习(13.6 对象移动)

13.6 对象移动 新标准的一个最主要的特性是可以移动而非拷贝对象的能力。如我们在13.1.1节(第440页)中所见&#xff0c;很多情况下都会发生对象拷贝。在其中某些情况下&#xff0c;对象拷贝后就立即被销毁了。在这些情况下&#xff0c;移动而非拷贝对象会大幅度提升性能。 如我…...

RHCE工程师特训指南

RHCE&#xff08;红帽认证工程师&#xff09;是Linux领域极具含金量的认证之一&#xff0c;其考试以实操为主&#xff0c;注重系统管理、网络服务配置及自动化运维能力。以下内容可帮助对RHCE考生高效规划学习路径。 一、RHCE认证概述 认证结构 RHCE认证分为两部分&#xff…...

内核、进程和线程---操作系统

操作系统 操作系统位于用户程序和硬件之间&#xff0c;通过系统调用提供接口可以让应用程序去使用硬件&#xff0c;但是硬件资源的管理和安全控制由操作系统负责。 用户空间和内存空间 在计算机系统中&#xff0c;内存可以分为两大区域&#xff1a;内核空间&#xff08;Ker…...

如何在 Postman 中上传图片并在请求中正确引用?

Postman 是一款常用的 API 测试工具&#xff0c;它不仅可以测试 API 的请求和响应&#xff0c;还支持多种数据格式包括图片。如何在 Postman 中传输图片&#xff1f; Postman 如何上传图片并在请求中使用教程...

平板实现 adb connect 连接的步骤

1. 检查设备的开发者选项 确保平板设备已开启开发者模式&#xff0c;并启用了USB调试。 2. 检查设备和电脑的网络连接 确保平板和电脑连接到同一个Wi-Fi网络&#xff0c;确认设备的 IP 地址是否正确。 通过 ping 命令测试&#xff1a; ping 192.168.3.243. 通过USB线进行初…...

安全+低碳+高效:Acrel-3000助力企业打造未来型电能管理体系-安科瑞黄安南

一 背景 电能因为方便传输、易于转换、便于控制等特性&#xff0c;成为广大企事业单位生产、办公最主要的能量来源。双碳背景下&#xff0c;由于电能清洁、高效、零排放的特点&#xff0c;能源消费侧将逐步以电代煤、以电代油、以电代气&#xff0c;形成以电为中心的能源消费体…...

专注自习室:番茄工作法实践

专注自习室&#xff1a;番茄工作法实践 我需要一个任务管理工具&#xff0c;但在网上找了很多都找不到合适的工具。市面上的大多数产品过于强调任务完成性&#xff0c;给我带来了很强的心理压力&#xff0c;这种压力最终反而降低了我的工作效率。于是我决定自己动手&#xff0…...

docker save如何迁移镜像更节省空间?

文章目录 方法一&#xff1a;使用docker save命令方法二&#xff1a;直接保存多个镜像到一个tar文件哪个方法更节省磁盘空间&#xff1f;空间效率对比实际测试示例其他优势结论 如何用脚本迁移加载镜像 迁移镜像时候&#xff0c;往往会碰到基础镜像相同的很多镜像需要迁移&…...

LeetCode算法题(Go语言实现)_16

题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …...

CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案

计算机该如何求解三角函数&#xff1f;或许你的第一印象是采用泰勒展开&#xff0c;或者采用多项式进行逼近。对于前者&#xff0c;来回的迭代计算开销成本很大&#xff1b;对于后者&#xff0c;多项式式逼近在较窄的范围內比较接近&#xff0c;超过一定范围后&#xff0c;就变…...

JVM 面经

1、什么是 JVM? JVM 就是 Java 虚拟机&#xff0c;它是 Java 实现跨平台的基石。程序运行之前&#xff0c;需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件&#xff1b;程序运行时&#xff0c;JVM 会对字节码文件进行逐行解释&#xff0c;翻译成机器码指令&#x…...

SEO(搜索引擎优化)详解

SEO&#xff08;搜索引擎优化&#xff09;详解 SEO是Search Engine Optimization的缩写&#xff0c;中文称为"搜索引擎优化"。它是指通过一系列技术和方法&#xff0c;提高网站在搜索引擎自然&#xff08;非付费&#xff09;搜索结果中的排名&#xff0c;从而获得更…...

Ubuntu平台下安装Node相关环境

说明&#xff1a;在进行VUE、TS等开发需要用到NodeJS相关环境&#xff0c;不同的项目有时候需要不同的Node版本支撑。本文将详细讲解NVM、Node、Yarn、PM2等环境安装的实施步骤。 测试服务器环境&#xff1a;22.04 LTS。 1. NVM 定义&#xff1a;Node Version Manager&#x…...

deepseek大模型一体机与deepseek的关系

deepseek大模型一体机与deepseek的关系 一、deepseek大模型一体机是什么 DeepSeek大模型一体机是由深度求索&#xff08;DeepSeek&#xff09;公司推出的软硬件一体化AI解决方案&#xff0c;旨在为企业提供高效、便捷的大模型部署和应用能力。 二、deepseek大模型一体机与de…...

Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站

开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组&#xff0c;开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App&#xff0c;登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…...

高等数学-第七版-上册 选做记录 习题7-2

1. 2....

基于Promise链式调用的多层级请求性能优化

代码优化-循环嵌套关联请求 1. 背景 在实际开发中&#xff0c;我们经常会遇到需要嵌套关联请求的场景&#xff0c;比如&#xff1a; 获取项目列表获取项目详情获取项目进度 2. 问题 在这种场景下&#xff0c;我们可能会遇到以下问题&#xff1a; 串行请求瀑布流&#xff…...

【强化学习】基于深度强化学习的微能源网能量管理与优化策略研究【Python】

目录 主要内容 程序要点 2.1 微能源网系统组成 2.2 强化学习及Q学习算法 部分代码 运行结果 下载链接 主要内容 该程序借助深度 Q 网络&#xff08;DQN&#xff09;&#xff0c;学习预测负荷、风 / 光可再生能源功率输出及分时电价等环境信息&#xff0c;运用…...

楼宇自控借何种技术,驱动建筑迈向高效绿色

在全球积极倡导可持续发展的大背景下&#xff0c;建筑行业作为能源消耗和碳排放的大户&#xff0c;实现高效绿色发展迫在眉睫。楼宇自控系统凭借其先进的技术手段&#xff0c;成为推动建筑向高效绿色转型的关键力量。那么&#xff0c;楼宇自控究竟借助哪些技术&#xff0c;让建…...

监控易一体化运维:监控易机房管理,打造高效智能机房

在数字化浪潮中&#xff0c;企业对数据中心和机房的依赖程度与日俱增&#xff0c;机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁&#xff0c;见证了机房管理从传统模式向智能化、精细化转变的过程。今天&#xff0c;就为大家深度剖析监控易在机房管理方面的卓越表现…...