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

news2024/10/7 18:23:21

引言

一、二分查找

基本概念

代码框架

二、二分查找

题目描述

解题思路及代码

结果展示

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

使用背景 

基本代码

引言

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

一、二分查找

基本概念

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

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

相关文章

Java毕业设计 基于SpringBoot 众筹网

Java毕业设计 基于SpringBoot 众筹网 SpringBoot 众筹网 功能介绍 注册 邮箱验证码 登录 忘记密码 首页 图片轮播 关于我们 项目列表 发布项目 我的添加项目 提交审核 已在募捐 项目详情 项目介绍 项目进展 捐赠列表 评论 新闻列表 发布新闻 新闻详情 评论新闻 联系我们 提交…

Android开发工程师面试题,2024年Android开发陷入饱和

前言 马上快到金三银四都春招阶段了&#xff0c;在这本就是跳槽、找工作的年后黄金时间&#xff0c;大多数求职者都早早做好年后求职的准备&#xff0c;其中不乏有年前早早辞了工作准备年后跳槽的有经验的职场老人们&#xff0c;也有一批即将毕业的应届毕业生的职场新人们。 …

redis使用笔记

redis使用笔记 1、Redis简介1.1 含义1.2 功能1.3 特点 2. 常用的数据结构2.1 HASH 3 redis接口定义3.1 redisReply3.2 redisContext3.3 redisCommand 4 实践操作4.1 遇到问题4.1.1 Get哈希的时候返回error4.1.2 长度一直为0&#xff0c;str没法打印&#xff08;未解决&#xff…

合泰HT66F2390----定时器中断学习笔记

前言 无需多言 直接开始定时器中断 的学习 通过上次的PWM学习&#xff0c;上次用的是周期型TM定时器模块 这次使用标准型TM定时器模块&#xff08;STM&#xff09; 代码 #include <HT66F2390.h>void Timer0_Init(void){_stm0c0 0b00001000;_stm0c1 0b11000001;_stm…

Android岗面试,android内存优化面试题

前言 曾听过很多人说Android学习很简单&#xff0c;做个App就上手了&#xff0c;工作机会多&#xff0c;毕业后也比较容易找工作。这种观点可能是很多Android开发者最开始入行的原因之一。 在工作初期&#xff0c;工作主要是按照业务需求实现App页面的功能&#xff0c;按照设…

22万字大模型面经整理+答案

槽位对齐&#xff08;slot alignment&#xff09; 在text2sql任务中&#xff0c;槽位对齐&#xff08;slot alignment&#xff09;通常指的是将自然语言问题中的关键信息&#xff08;槽位&#xff09;与数据库中的列名或API调用中的参数进行匹配的过程。这个过程中&#xff0c…

PTA L2-001 紧急救援

作为一个城市的应急救援队伍的负责人&#xff0c;你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候&#xff0c;你的任务是带领你的…

leetcode 热题 100_最小覆盖子串

题解一&#xff1a; 双指针滑动窗口&#xff1a;暴力解法——用双指针来表示字符串s中的子串首尾&#xff0c;遍历所有子串并与字符串t判断是否符合条件。我们可以对遍历和判断的过程进行优化&#xff0c;首先是遍历&#xff0c;右指针先移动直到涵盖所以需要的字母&#xff0c…

大数据技术学习笔记(五)—— MapReduce(2)

目录 1 MapReduce 的数据流1.1 数据流走向1.2 InputFormat 数据输入1.2.1 FileInputFormat 切片源码、机制1.2.2 TextInputFormat 读数据源码、机制1.2.3 CombineTextInputFormat 切片机制 1.3 OutputFormat 数据输出1.3.1 OutputFormat 实现类1.3.2 自定义 OutputFormat 2 Map…

【Software Platform Bundle】

https://www.ni.com/zh-cn/support/downloads/software-products/download.software-platform-bundle.html

蓝桥杯倒计时 38 天

整数二分模板&#xff1a;数的范围 二分的本质不是单调性&#xff0c;而是二分出能满足某种性质使得将整数分成两半。 思考&#xff1a;模板题&#xff0c;模板记熟就能做 #include<iostream> using namespace std; int n,q; const int N 1e510; int a[N]; int main…

大海捞针:用代码聚类寻找恶意 PyPI 包(ASE 2023)

A Needle is an Outlier in a Haystack: Hunting Malicious PyPI Packages with Code Clustering Institute of Software, Chinese Academy of Sciences, Beijing, China;University of Chinese Academy of Sciences, Beijing, China Abstract 作为最流行的Python软件存储库&…

Android开发必须会的技能,记得把每一次面试当做经验积累

前言 本来已经在为去大厂工作摩拳擦掌的Android开发者们&#xff0c;今年显得格外艰难&#xff1a; 待就业数高达874万&#xff01;人才竞争加剧&#xff01;疫情让大多数公司的招聘需求缩减&#xff01;人才招聘要求愈来愈高&#xff01; 别说offer&#xff0c;现在出门零活…

Android开发基础面试题,Android保活黑科技的技术实现

前言 Android常用知识体系是什么鬼&#xff1f;所谓常用知识体系&#xff0c;就是指对项目中重复使用率较高的功能点进行梳理。注意哦&#xff0c;不是Android知识体系。 古语道&#xff1a;学而不思则罔&#xff0c;思而不学则殆。如果将做项目类比为“学”&#xff0c;那么…

Unity2023.1.19_DOTS_JobSystem

Unity2023.1.19_DOTS_JobSystem 上篇我们知道了DOTS是包含Entity Component System&#xff0c;Job System&#xff0c;Burst compiler三者的。接下来看下JobSystem的工作原理和具体实现。 简介&#xff1a; 官方介绍说&#xff1a;JobSystem允许您编写简单而安全的多线程代…

【模型训练】-图形验证码识别

针对网站中的图形验证码图片&#xff0c;进行反向的内容识别&#xff0c;支持数字和字母&#xff0c;不区分大小写。 ​​​​​​​​​​​​​​数据集地址 数据格式如下&#xff1a; 1、依赖导入 import os import torch import torch.nn as nn import torch.optim as o…

GPT vs Gemini vs Claude 测试大比拼 到底谁是最强王者?

Anthropic发布的通用大语言模型Claude&#xff0c;在各项能力方面号称是全方面超越GPT&#xff0c;实测究竟如何呢&#xff1f;这次测试顺便把前段时间发布的Gemini拉上一起做对比&#xff01;主要是以一些有趣幽默的脑筋急转弯为题目&#xff0c;来看看不同大模型对此的反馈。…

闰年导致的哪些 Bug

每次闰年对程序员们都是一个挑战&#xff0c;平时运行好好的系统&#xff0c;在 02-29 这一天&#xff0c;好像就会有各种毛病。 虽然&#xff0c;提前一天&#xff0c;领导们都会提前给下面打招呼。但是&#xff0c;不可避免的&#xff0c;今天公司因为闰年还是有一些小故障。…

SpringBoot中集成LiteFlow(轻量、快速、稳定可编排的组件式规则引擎)实现复杂业务解耦、动态编排、高可扩展

场景 在业务开发中&#xff0c;经常遇到一些串行或者并行的业务流程问题&#xff0c;而业务之间不必存在相关性。 使用策略和模板模式的结合可以解决这个问题&#xff0c;但是使用编码的方式会使得文件太多, 在业务的部分环节可以这样操作&#xff0c;在项目角度就无法一眼洞…