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

引言

一、二分查找

基本概念

代码框架

二、二分查找

题目描述

解题思路及代码

结果展示

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

使用背景 

基本代码

引言

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

一、二分查找

基本概念

        二分查找是一种在有序数组中查找特定元素的高效算法。它的核心思想是将目标值与数组中间的元素进行比较,根据比较结果缩小搜索范围,从而逐步逼近目标值。在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;
}

文末小结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

95、评估使用多线程优化带来的性能提升

本节评估一下&#xff0c;通过对卷积的 co 维度进行多线程切分之后&#xff0c;对于模型的性能提升。 评估下性能 在进行多线程程序运行时&#xff0c;建议电脑中的 CPU 不要有其他繁重的任务执行。 在相同的环境下&#xff0c;分别运行 5th_codegen 和 6th_multi_thread 下的…

Pytorch 复习总结 6

Pytorch 复习总结&#xff0c;仅供笔者使用&#xff0c;参考教材&#xff1a; 《动手学深度学习》Stanford University: Practical Machine Learning 本文主要内容为&#xff1a;Pytorch 计算机视觉。 本文先介绍了计算机视觉中两种常见的改进模型泛化性能的方法&#xff1a…

香港投资+移民计划高峰论坛圆满落幕洞察趋势,探索未来财富之路

3月4日&#xff0c;由中国香港太阳联合资本有限公司牵头举办的「香港投资移民计划高峰论坛」在港交所圆满结束。吸引超260位高净值人士参加&#xff0c;已收到近600个投资移民意向。此次论坛汇聚了来自世界各地的投资移民专家、企业家、以及潜在投资者&#xff0c;共同探讨香港…

网络编程(3/4)

广播 ​ #include<myhead.h>int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_INET, SOCK_DGRAM, 0);if(sfd -1){perror("socket error");return -1;}//2、将套接字设置成允许广播int broadcast 1;if(setsockopt(sfd, SOL_SOC…

docker部署前后端分离项目

docker部署前后端分离项目 前提&#xff0c;服务器环境是docker环境&#xff0c;如果服务器没有安装docker&#xff0c;可以先安装docker环境。 各个环境安装docker&#xff1a; Ubuntu上安装Docker&#xff1a; ubuntu离线安装docker: CentOS7离线安装Docker&#xff1a; Cen…

如何给Vue项目配置好一个nginx.conf文件?

如何给Vue项目配置好一个nginx.conf文件&#xff1f; 一般前端项目中&#xff0c;会有一个docker/nginx/nginx.conf文件&#xff0c;用于配置DockerFile配置等。 那么&#xff0c;如何给项目写好一个nginx.conf文件&#xff0c;以DockerFile为例&#xff1a; # 使用 Node.js …

【LeetCode】并查集OJ

目录 1.省份数量 2. 等式方程的可满足性 1.省份数量 题目地址&#xff1a; 547. 省份数量 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a;对于该题我们直接使用并查集&#xff0c;将可以直接的城市都归类一个集合&#xff0c;最后统计数组中集合的总数就是…

Qt入门(一)Qt概述

Qt是什么&#xff1f; Qt是一个跨平台应用开发框架。 Qt既包括了一系列的Qt库&#xff0c;还包括诸多配套的开发工具如QtCreater&#xff0c;GUI Designer。Qt本身是由C开发的&#xff0c;但是也提供了其他编程语言的接口。 Qt的定位以及同类 学一种技术&#xff0c;最重要的是…

WordPress建站入门教程:忘记数据库名称、用户名和密码了怎么办?

有时候我们需要进入phpMyAdmin管理一些数据库&#xff0c;但是登录phpMyAdmin时却需要我们输入数据库的用户名和密码&#xff0c;但是我们不记得了应该怎么办呢&#xff1f; 其实&#xff0c;我们只需要进入WordPress网站根目录找到并打开wp-config.php文件&#xff0c;就可以…

FPGA- RGB_TFT显示屏原理及驱动逻辑

下图是TFT显示屏的显示效果 该显示屏共分为 2 个版本&#xff0c;4.3 寸版本的 TFT4.3’’_V3.0 和 5.0 寸版本的 TFT5.0’’_V3.0。 两者 PCB 背板电路完全相同&#xff0c;接口脚位定义完全相同&#xff0c;接口时序完全相同&#xff0c;仅使用的显示屏 模组尺寸不同。设计两…

多线程相关面试题(2024大厂高频面试题系列)

1、聊一下并行和并发有什么区别&#xff1f; 并发是同一时间应对多件事情的能力&#xff0c;多个线程轮流使用一个或多个CPU 并行是同一时间动手做多件事情的能力&#xff0c;4核CPU同时执行4个线程 2、说一下线程和进程的区别&#xff1f; 进程是正在运行程序的实例&#xff…

【Linux】常见指令1(ls指令、pwd指令、cd指令、touch指令、mkdir指令、rmdir指令、man指令、cp指令、mv指令、cat指令)

目录 01.ls指令与ll指令 02.pwd指令 03.cd指令 04.touch指令 05.mkdir指令 06.rmdir指令&&rm指令 07.man指令 08.cp指令 09.mv指令 10.cat指令 01.ls指令与ll指令 ls指令&#xff1a; 原型&#xff1a;list directory contents 语法&#xff1a;ls[选项][目录…

于建筑外窗遮阳系数测试的太阳光模拟器模拟太阳光照射房屋视频

太阳光模拟器是一种用于测试建筑外窗遮阳系数的高科技设备。它能够模拟太阳光照射房屋的情景&#xff0c;帮助建筑师和设计师更好地了解建筑外窗的遮阳性能&#xff0c;从而提高建筑的能源效率和舒适度。 这种模拟器的工作原理非常简单&#xff0c;它通过使用高亮度的光源和精密…

【音视频开发好书推荐】RTC程序设计:实时音视频权威指南

目录 1、WebRTC概述2、好书推荐3、本书内容4、本书特色5、作者简介6、谁适合看这本书 1、WebRTC概述 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个由Google发起的实时音视频通讯C开源库&#xff0c;其提供了音视频采集、编码、网络传输&#xff0c;解码显…

【python高级编程教程】笔记(python教程、python进阶)第三节:(1)多态与鸭子类型(Polymorphism and Duck Typing)

参考文章1&#xff1a;【比刷剧还爽】清华大佬耗时128小时讲完的Python高级教程&#xff01;全套200集&#xff01;学不会退出IT界&#xff01; 参考文章2&#xff1a;清华教授大力打造的Python高级核心技术&#xff01;整整100集&#xff0c;强烈建议学习&#xff08;Python3…

集成算法(随机森林,AdaBoost,Xgboost,Stacking模型)

目录 一、前言 二、Bagging模型 三、Boosting模型 四、Stacking模型 五、总结 一、前言 集成算法&#xff08;Enseamable learning&#xff09; 集成算法一般考虑树模型&#xff0c;KNN就不太适合 目的&#xff1a;让机器学习效果更好&#xff0c;单个不好&#xff0c;一起…

【力扣白嫖日记】626.换座位

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 626.换座位 表&#xff1a;Seat 列名类型idintstudentvarchar id 是该表的主键&#xff08;唯一值&#xf…

Golang各版本的GC详解

go v1.3的标记清除法 清除的第一步&#xff1a;stw将可达对象标记删除未被标记对象 go v1.5三色标记法 从根节点出发&#xff0c;将下一个节点遍历为灰色&#xff0c;放入灰色集合中遍历灰色节点集合&#xff0c;把灰色能到达的节点标记为灰色&#xff0c;把自身标记为黑色&a…

UniSA: Unified Generative Framework for Sentiment Analysis

文章目录 UniSA&#xff1a;统一的情感分析生成框架文章信息研究目的研究内容研究方法1.总体架构图2.基准数据集SAEval3.Task-Specific Prompt4.Modal Mask Training5.Pre-training Tasks5.1Mask Context Modeling5.2Sentiment Polarity Prediction5.3Coarse-grained Label Con…

latex使用\rm将部分公式或者部分单词设置为正体

在LaTeX中&#xff0c;\rm 是用于设置文字为 “Roman” 字体的命令。这里的 “Roman” 字体通常指的是默认的文本字体&#xff0c;也就是没有特意设置为斜体或粗体的普通字体。然而&#xff0c;\rm 并不总是表示特定的字体样式&#xff0c;而是依赖于当前文档或环境的设置。 在…