备战蓝桥杯————二分搜索(一)

引言

一、二分查找

基本概念

代码框架

二、二分查找

题目描述

解题思路及代码

结果展示

三、寻找左侧边界的二分搜索

使用背景 

基本代码

引言

        在计算机科学的世界里,二分查找算法无疑是一种经典且强大的工具。它以其高效的性能,在有序数据集中快速定位元素,成为了算法库中不可或缺的一部分。然而,二分查找的应用场景远不止于此。在某些特定情况下,我们需要找到元素的边界位置,例如,在有序数组中寻找一个值的左侧边界。本文将探讨如何通过二分查找算法来实现这一目标,并详细分析算法的每个关键步骤,确保读者能够充分理解并掌握这一技巧

一、二分查找

基本概念

        二分查找是一种在有序数组中查找特定元素的高效算法。它的核心思想是将目标值与数组中间的元素进行比较,根据比较结果缩小搜索范围,从而逐步逼近目标值。在Java、C++、Python、Go和JavaScript等编程语言中,二分查找的实现框架基本相同,但细节处理上可能有所不同。

代码框架

        以下是一个Java语言实现的二分查找框架:


public int binarySearch(int[] nums, int target) {int left = 0, right = nums.length - 1; // 初始化左右边界while (left <= right) { // 循环条件,确保左边界小于等于右边界int mid = left + (right - left) / 2; // 防止整数溢出的中间位置计算if (nums[mid] == target) {// 找到目标值,处理找到的情况} else if (nums[mid] < target) {left = mid + 1; // 如果中间值小于目标值,更新左边界} else {right = mid - 1; // 如果中间值大于目标值,更新右边界}}return ...; // 返回结果,可能是索引或特定值
}

在实现二分查找时,有几个细节需要注意:

1. 循环条件:确保在搜索范围内进行,即left <= right。
2. 中间位置的计算:使用left + (right - left) / 2而不是(left + right) / 2来避免整数溢出。
3. 边界更新:根据中间值与目标值的比较结果,更新左边界或右边界。
4. 返回值:如果找到目标值,返回其索引;如果未找到,返回一个特定的值(如-1)表示未找到。

        通过这个框架,我们可以清晰地理解二分查找的逻辑流程,并根据具体需求调整实现细节。我们将通过实例来分析这些细节可能带来的变化,并探讨如何在不同编程语言中实现二分查找。

二、二分查找

题目描述

        给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums= [-1,0,3,5,9,12], target= 9
输出: 4
解释: 9 出现在 nums中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target= 2
输出: -1
解释: 2 不存在 nums中因此返回 -1

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间。

解题思路及代码

        这道题使用常规的二分查找技术即可,找到与目标值相等的数值,返回其索引。

class Solution {public int search(int[] nums, int target) {int start=0,end=nums.length-1;while(start<=end){int mid=start+(end-start)/2;if(nums[mid]==target)return mid;else if(nums[mid]<target)start=mid+1;else if(nums[mid]>target)end=mid-1;}return -1;}
}

结果展示

三、寻找左侧边界的二分搜索

使用背景 

       在二分查找中,我们通常寻找目标值在有序数组中的位置。但有时我们可能需要找到目标值的左侧边界,即大于或等于目标值的第一个元素的索引。以下是实现这一功能的二分查找算法的常见代码形式,以及一些需要注意的细节。

基本代码

int left_bound(int[] nums, int target) {int left = 0;int right = nums.length; // 注意:初始化右边界为数组长度,而不是数组长度减一while (left < right) { // 注意:循环条件使用 < 而不是 <=int mid = left + (right - left) / 2;if (nums[mid] == target) {right = mid; // 缩小搜索区间的上界} else if (nums[mid] < target) {left = mid + 1; // 搜索右半部分} else {right = mid; // 搜索左半部分}}return left; 
}

1. 为什么循环条件是 left < right 而不是 left <= right?

答:这是因为我们在初始化右边界时使用了 nums.length 而不是 nums.length - 1。这样,搜索区间始终是左闭右开的 [left, right)。当 left == right 时,搜索区间为空,循环终止。

2. 为什么没有返回 -1的操作?如果数组中不存在目标值怎么办?

答:在返回之前,我们需要检查 nums[left]是否等于目标值。如果不等于,说明目标值不存在于数组中,应返回 -1。同时,我们需要确保索引不越界。

3. 为什么更新边界时使用 left = mid + 1 和 right = mid?

答:这是因为我们的搜索区间是左闭右开的,所以当 nums[mid] 被检测后,我们需要在 [mid + 1, right)或 [left, mid) 中继续搜索。

4. 为什么该算法能够找到左侧边界?

答:关键在于处理 nums[mid] == target 的情况时,我们不立即返回,而是缩小搜索区间的上界 right,继续在左侧区间 [left, mid)`中搜索。

5. 为什么返回 left 而不是 right?

答:因为循环终止条件是 left == right,此时 left 就是目标值的左侧边界。

6. 如何使用两边都闭的搜索区间?

答:我们可以将右边界初始化为 nums.length - 1,并将循环条件改为 left <= right。

调整后的代码


int left_bound(int[] nums, int target) {int left = 0, right = nums.length - 1; // 初始化右边界为数组长度减一while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;} else if (nums[mid] == target) {right = mid - 1; // 收缩右侧边界}}// 检查 target 是否存在于 nums 中if (left < 0 || left >= nums.length || nums[left] != target) {return -1;}return left;
}

文末小结

        通过本文的讨论,我们不仅学习了如何实现寻找左侧边界的二分查找算法,还深入了解了算法背后的逻辑和细节。这种算法的变体在处理边界问题时提供了一种优雅且高效的解决方案。希望读者能够将这些知识应用到实际编程实践中,无论是在面试准备、学术研究还是日常开发工作中。记住,理解算法的本质和掌握其变体是成为一名优秀程序员的关键。感谢您的阅读,期待在下一篇文章中与您再次相遇。

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

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

相关文章

Windows10安装Docker

使用 PowerShell 启用 Hyper-V 以管理员身份打开 PowerShell 控制台。 运行以下命令&#xff1a; PowerShell复制 Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All如果无法找到此命令&#xff0c;请确保你以管理员身份运行 PowerShell。 安装…

Android大厂高级面试题灵魂100问,带你彻底弄明白

“2020年技术没有成长&#xff0c;我今年一定要好好努力学习&#xff01;” “在现在这个公司都工作了3年了&#xff0c;一毛钱工资都没有涨…” “年前真倒霉&#xff0c;老板嫌我工资高&#xff0c;被优化了&#xff0c;年后又遇到了疫情&#xff0c;现在都还没有找到合适的工…

从Win转Mac,我的感受如何

文章目录 前言MacBook优点美观动画流畅安装软件方便轻便、续航强大多数命令和Linux通用系统稳定、安全做工精美、视听体验好CPU性能较好触控板体验好 MacBook缺点缺乏部分软件部分操作逻辑不是很科学&#xff1f;玩不了多少游戏 总结与展望 前言 整个大学期间&#xff0c;我的主…

【论文翻译】结构化状态空间模型

文章目录 3.2 对角结构化状态空间模型3.2.1 S4D:对角SSM算法3.2.2 完整应用实例 3.3 对角化加低秩&#xff08;DPLR&#xff09;参数化3.3.1 DPLR 状态空间核算法3.3.2 S4-DPLR 算法和计算复杂度3.3.3赫尔维兹&#xff08;稳定&#xff09;DPLR形式 这篇文章是Mamba作者博士论文…

LLM量化、高保真图生视频、多模态肢体运动生成、高分辨率图像合成、低光图像/视频增强、相机相对姿态估计

本文首发于公众号&#xff1a;机器感知 LLM量化、高保真图生视频、多模态肢体运动生成、高分辨率图像合成、低光图像/视频增强、相机相对姿态估计 EasyQuant: An Efficient Data-free Quantization Algorithm for LLMs Large language models (LLMs) have proven to be very s…

android实战视频教程,flutter开发实战详解pdf

前言 这是一篇软文、但是绝对不是鸡汤&#xff1b;为啥不是呢&#xff1f;因为我文笔太差…偶尔矫情发发牢骚&#xff08;勿喷&#xff09; 说说程序猿行业 现在社会上给IT行业贴上了几个标签&#xff1a;高薪、高危、高大上、秃顶&#xff08;哈哈&#xff09;。这些标签我…

C++的类与对象(三)

目录 类的6个默认成员函数 构造函数 语法 特性 析构函数 特性 类的6个默认成员函数 问题&#xff1a;一个什么成员都没的类叫做空类&#xff0c;空类中真的什么都没有吗&#xff1f; 基本概念&#xff1a;任何类在什么都不写时&#xff0c;编译器会自动生成以下六个默认…

Linux 性能优化的全景指南,都在这一篇里了,建议收藏!

Linux 性能优化 性能指标 高并发和响应快对应着性能优化的两个核心指标&#xff1a;吞吐和延时 应用负载角度&#xff1a;直接影响了产品终端的用户体验 系统资源角度&#xff1a;资源使用率、饱和度等 性能问题的本质就是系统资源已经到达瓶颈&#xff0c;但请求的处理还…

MySQL下实现纯SQL语句的递归查询

需求 有一个部门表&#xff0c;部门表中有一个字段用于定义它的父部门&#xff1b; 在实际业务中有一个『部门中心』的业务&#xff1b; 比如采购单&#xff0c;我们需要显示本部门及子部门的采购单显示出来。 结构 数据如下&#xff1a; 实现方式如下&#xff1a; WITH RECUR…

内衣洗衣机名牌排行榜前十名:十款强大性能内衣洗衣机精心力荐

小型内衣洗衣机一般是为婴儿宝宝&#xff0c;或者一些有特殊需要的用户而设计使用的&#xff0c;宝宝衣物换洗频繁&#xff0c;而且对卫生方面的除菌要求高&#xff0c;而为避免交叉感染&#xff0c;所以一般不适合和大人的衣物放在一起洗&#xff0c;因此对于有宝宝的家庭来说…

Android多线程实现方式及并发与同步,Android面试题汇总

一. 开发背景 想要成为一名优秀的Android开发&#xff0c;你需要一份完备的知识体系&#xff0c;在这里&#xff0c;让我们一起成长为自己所想的那样。 我们的项目需要开发一款智能硬件。它由 Web 后台发送指令到一款桌面端应用程序&#xff0c;再由桌面程序来控制不同的硬件设…

Plasmo框架开发浏览器插件配置newtab页面,并可以跳转

有关plasmo框架添加页面可以看官方文档&#xff1a;Browser Extension Pages – Plasmo 想要给插件添加一个页面&#xff0c;可以通过添加newtab.tsx添加&#xff1a; 或者通过添加tabs文件夹添加多个页面&#xff1a; 想要访问的话&#xff0c;只需要通过&#xff1a;chrome-…

Python爬虫实战第三例【三】【上】

零.实现目标 爬取视频网站视频 视频网站你们随意&#xff0c;在这里我选择飞某速&#xff08;狗头保命&#xff09;。 例如&#xff0c;作者上半年看过的“铃芽之旅”&#xff0c;突然想看了&#xff0c;但是在正版网站看要VIP&#xff0c;在盗版网站看又太卡了&#xff0c;…

2024年腾讯云轻量16核32G28M服务器优惠价格3468元15个月

2024年腾讯云轻量16核32G28M服务器优惠价格3468元15个月&#xff0c;380GB SSD云硬盘&#xff0c;6000GB月流量。 一张表看懂腾讯云服务器租用优惠价格表&#xff0c;一目了然&#xff0c;腾讯云服务器分为轻量应用服务器和云服务器CVM&#xff0c;CPU内存配置从2核2G、2核4G、…

Linux下du命令和df命令的使用

du命令作用是估计文件系统的磁盘已使用量&#xff0c;常用于查看文件或目录所占磁盘容量。df命令是统计磁盘使用情况&#xff0c;可以用来查看磁盘已被使用多少空间和还剩余多少空间。du命令语法du [选项] [文件或目录名称]参数&#xff1a;-a&#xff1a;--all&#xff0c; 列…

C#,数值计算,求解微分方程的预测校正法(修正欧拉法)算法与源代码

Leonhard Euler 1 微分方程 微分方程&#xff0c;是指含有未知函数及其导数的关系式。解微分方程就是找出未知函数。 微分方程是伴随着微积分学一起发展起来的。微积分学的奠基人Newton和Leibniz的著作中都处理过与微分方程有关的问题。微分方程的应用十分广泛&#xff0c;可…

To 有缘看到的朋友,To myself

To 有缘看到的朋友&#xff0c;To myself 零、00时光宝盒 我们生而为人&#xff0c;而不是什么神仙妖怪&#xff0c;自然逃不脱凡尘种种不易。 世界并不完美&#xff0c;面对很多事情我们都很无奈甚至悲哀&#xff0c;但生活总要继续下去&#xff0c;当困难悄悄地来临&#xff…

【vue3之组合式API】

组合式API 一、setup1.写法2.如何访问3.语法糖4.同步返回对象 二、reactive()和ref()1.reactive()2.ref() 三、computed四、watch函数1侦听单个数据2.侦听多个数据3. immediate4. deep5.精确侦听对象的某个属性 五、生命周期函数六、组件通信1.父传子2. 子传父 七、模版引用1. …

shell脚本一键部署docker

Docker介绍 Docker 是一个开源的平台&#xff0c;用于开发、交付和运行应用程序。它利用容器化技术&#xff0c;可以帮助开发人员更轻松地打包应用程序及其依赖项&#xff0c;并将其部署到任何环境中&#xff0c;无论是开发工作站、数据中心还是云中。以下是 Docker 的一些关键…

【Linux】软件包管理器yum

目录 一、yum是什么&#xff1f; 二、查看软件包 三、安装与卸载软件 1、如何安装软件 2、如何卸载软件 四、yum源的配置 一、yum是什么&#xff1f; 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人…