基础算法---二分查找

news2024/11/20 1:46:27

文章目录

  • 基本思想
  • 1.数的范围
  • 2.搜索旋转排序数组
  • 3.搜索插入位置
  • 4.x的平方根
  • 总结

在这里插入图片描述

基本思想

二分查找的必要条件并不是单调,而是当我给定一个边界条件,然后左边满足这个边界条件,右边不满足这个边界条件,然后可以查找这个临界点,这就是二分查找
在这里插入图片描述
接下来我们具体讨论该怎么做

我们先讨论满足这个条件的一边,首先我们取mid=(l+r)/2,如果这个mid<x证明mid在x的左边,mid可能是边界所以要包含mid,所以将范围更新为[mid,r],如果mid>x,证明mid在x的右边,由于右边是不满足条件的,所以直接把mid舍去,更新范围为[l,mid-1],以此类推最后当l==r的时候,就是边界x

第二种:我们来讨论一下不满足条件的一边,如果我们需要找到右边界x,那么首先定义一个mid=(l+r+1)/2,如果mid<x证明不满足右边条件的在右边,所以要将mid舍去,将范围更新为[mid+1,r],如果mid>x证明mid在x的右边,所以满足右边的条件,由于右边都可能存在满足条件的,所以不能舍弃边界mid,所以将边界更新为[l,mid].

大致就分为上面两种情况,注意:如果是第二种情况的时候,需要+1,因为如果不向上取整的话,会造成死循环,如果不向上取整的话,当l=r-1的时候,意思就是当l和r相差1的时候,mid始终等于l这样就产生了死循环,但是如果向上取整的话,最后mid就等于r,就会跳出循环

接下来我们了解了基本算法来练习两道题:

1.数的范围

在这里插入图片描述

根据题目描述可以知道,这道题可以用二分查找

#include<iostream>
using namespace std;
//数组大小和需要的变量
const int N=100000;
int a[N];
int q,n;
int main()
{
	//输入变量
    cin>>n>>q;
    //初始化数组
    for(int i=0;i<n;i++)cin>>a[i];
    //q行数据
    while(q>0)
    {
    	//输入需要查找的数据
        int x;
        cin>>x;
        //先定义左右边界
        int l=0,r=n-1;
        while(l<r)
        {
        	//二分
            int mid=(l+r)/2;
            //边界条件
            if(a[mid]>=x)r=mid;
            else l = mid+1;
        }
        //出循环判断l对应的值是否和x相等,如果相等则继续,如果不相等则直接打印-1 -1
        if(a[l]!=x)cout<<"-1 -1"<<endl;
        else
        {
        	//先输出上个循环的l
            cout<<l<<' ';
            //确定边界
            int l=0,r=n-1;
            //对右边界的条件进行二分
            while(l<r)
            {
                int mid=(l+r+1)/2;//向上取整,防止死循环
                if(a[mid]<=x)l=mid;
                else r=mid-1;
            }
            //输出有边界
            cout<<l<<endl;
        }
        q--;
    }
    return 0;
}

2.搜索旋转排序数组

在这里插入图片描述

思路:首先这道题要求时间复杂度是O(logn),那么首先想到的就是二分,虽然这道题给的不是一个完整的有序的数组,但是是局部有序的 ,我们二分之后总是能保证左区间或者右区间是有序的,所以我们只需要判断一个有序区间是否存在这个数,如果不存在说明在另一个区间,直接else进入另一个区间,所以第一个大的if else是讨论左区间和右区间的有序性,第二个if else是讨论是在左区间或者右区间,去对这个数组的范围进行更新,范围条件,如果mid对应的值和target相等直接返回下标mid,如果最后不相等,直接跳出循环返回-1

代码展示

int search(int* nums, int numsSize, int target) {
    if(numsSize==1)
    {
        return nums[0]==target?0:-1;
    }
    int l=0;
    int r=numsSize-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(nums[mid]==target)
        {
            return mid;
        }
        if(nums[mid]>=nums[l])
        {
            if(nums[mid]>target&&nums[l]<=target)
            {
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }
        else{
            if(nums[mid]<target&&target<=nums[r])
            {
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
    }
    return -1;
}

3.搜索插入位置

在这里插入图片描述

这道题也是一个简单的二分,注意边界条件即可

int searchInsert(int* nums, int numsSize, int target) {
    if(target>nums[numsSize-1])
    {
        return numsSize;
    }
    int l=0,r=numsSize-1;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(nums[mid]>=target)r=mid;
        else l=mid+1;
    }
    return l;
}

4.x的平方根

在这里插入图片描述

这道题是一道简单的二分

首先定义左边界和右边界,然后定义一个范围值ans,然后进行二分如果中间值的平方<=x说明答案在右边,将ans更新,然后更新区间范围,如果两个数的乘积大于x的话说明在在区间的左边,所以更新r,由于我们需要的是向下取整,所以在更新l的时候,就直接更新ans,如果在r变化的时候更新ans会使最后的ans变大

int mySqrt(int x) {
    int l=0;
    int r=x;
    int ans=-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if((long long)mid*mid<=x)
        {
            ans=mid;
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    return ans;
}

总结

当你理解了二分查找的原理,并且掌握了它的实现方法,你就掌握了一种高效查找数据的技巧。二分查找是一种简单而又强大的算法,在处理大规模数据时能够显著提高搜索效率。通过不断地练习和应用,你可以在编程的世界里更加游刃有余地运用这一技巧。希望本文对你有所启发,能够帮助你更深入地理解二分查找算法,并在实际应用中发挥其作用。在编程的道路上,不断学习,不断进步,愿你能够越走越远,探索更多的算法与数据结构的奥秘。

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

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

相关文章

统一所有 LLM API:支持预算与速率限制 | 开源日报 No.229

BerriAI/litellm Stars: 6.7k License: NOASSERTION litellm 是一个使用 OpenAI 格式调用所有 LLM API 的工具。它支持 Bedrock、Azure、OpenAI、Cohere、Anthropic 等 100 多种 LLMs&#xff0c;提供企业级代理服务器和稳定版本 v1.30.2。 主要功能和优势包括&#xff1a; 将…

电机控制专题(三)——Sensorless之有功磁链Active Flux电压模型

文章目录 电机控制专题(三)——Sensorless之有功磁链Active Flux电压模型前言理论推导仿真验证总结参考文献 电机控制专题(三)——Sensorless之有功磁链Active Flux电压模型 前言 总结下电机控制中的有功磁链Active Flux(AF)模型。 纯小白&#xff0c;如有不当&#xff0c;轻…

OceanBase V4.2特性解析:用 Show Trace 快速定位数据库性能瓶颈

在数据库日常运维中&#xff0c;当遇到慢SQL问题时&#xff0c;若无法迅速查明原因&#xff0c;将极大地影响用户的使用感受&#xff0c;甚至可能引发业务或服务的中断。相较于单机数据库&#xff0c;分布式数据库系统因其涉及多个节点和多组件的协同工作&#xff0c;集群规模可…

数仓建模—物理数据模型

文章目录 数仓建模—物理数据模型什么是物理数据模型物理数据模型示例如何构建物理数据模型物理数据模型与逻辑数据模型逻辑模型和物理模型之间有什么关系逻辑数据模型的好处物理数据模型的好处数仓建模—物理数据模型 前面我们讲了数据模型和逻辑数据模型,你可以参考前面的文…

Linux配置环境变量_推荐的方式

Linux配置环境变量_推荐以下两种方法&#xff1a; (1)用户环境变量&#xff1a;编辑用户目录下 ~/.bashrc、~/.bash_profile 或 ~/.profile文件 (2)系统环境变量&#xff1a;在/etc/profile.d/目录&#xff0c;创建独立的.sh文件 环境变量脚本文件的执行顺序 /etc/profile-&g…

npm i 依赖下载失败

git config --global url."https://".insteadOf git://解决npm install 报错 npm ERR code 128 Permission denied_please make sure you have the correct access right-CSDN博客

paddlepaddle-gpu安装

背景 之前安装paddlepaddle-gpu遇到各种问题&#xff0c;安装不成功&#xff0c;之前使用了wsldocker的方式&#xff0c;可查看我之前博客&#xff1a;记录paddlepaddle-gpu安装&#xff0c;这要会导致我整个开发流程比较割裂 cuda版本 强烈推荐cuda11.8&#xff0c;paddlep…

flutter release 报错 Error: SocketException: Failed host lookup:

flutter 的 debug 模式没有任何问题 &#xff0c;打了release 包后一直报下面的错&#xff0c;查了一下是 因为没有网络权限 Error: SocketException: Failed host lookup: yomi-test-aws-sg.yomigame.games (OS Error: No address associated with hostname, errno 7) 按照下…

C语言-rand+srand+time的使用

1.随机数字的生成 rand 随机数字的生成需要rand&#xff0c;这里需要知道的是rand需要头文件是stdlib&#xff0c;也就是#include<stdlib.h>。 这里的循环可以用for 所以我们可以在主函数里面写出 #include<stdio.h> #include<stdlib.h>//rand头文件int …

中仕公考:教师编制和事业单位d类一样吗?

教师编制和事业单位D类在考试内容、专业要求、晋升途径等方面有很大的不同中仕为大家介绍一下&#xff1a; 考试内容&#xff1a;教师编的考试包括教育综合知识和学科专业知识&#xff0c;有的地区会额外考公共基础知识。事业单位D类的考试更侧重于职业能力倾向测验和综合应用…

机器学习理论公式推导及原理—决策树

机器学习公式推导及原理—决策树 根据西瓜书中的公式与内容来进行推导和实现 算法原理 从逻辑角度&#xff0c;一堆if else语句的组合从几何角度&#xff0c;根据某种准则划分特征空间。最终目的&#xff1a;将样本越分越“纯。 信息熵的概念 自信息&#xff1a;是指随机变量…

嵌入式学习55-ARM4(ADC和I²C)

1、什么是ADC,模拟量和数字量有什么特点&#xff1f; ADC&#xff1a; …

Review on Psychological Stress Detection Using Biosignals 利用生物信号检测心理压力综述

https://ieeexplore.ieee.org/document/8758154 问题背景 和压力相关的生物信号包括&#xff1a; 生理&#xff1a;EEG、心电图、EDA、肌电图物理测量&#xff1a;呼吸频率、言语、皮肤温度、瞳孔大小、眼睛活动 压力的维度&#xff1a;心理、行为和生理 压力体验与反馈 下…

【VI/VIM】基本操作备忘录

简介 新建/打开文件 工作模式 常用命令 移动命令 文本选中 撤销、删除 复制粘贴 替换 缩排 查找 替换 插入 分屏 练习

API请求报错 Required request body is missing问题解决

背景 在进行调用的时候&#xff0c;加载方法&#xff0c;提示以下错误 错误信息如下&#xff1a; {"code": 10001,"msg": "Required request body is missing: XXX","data": null,"extra": null }Required request body…

【热门话题】探索与心得:深入体验Microsoft Edge浏览器

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 探索与心得&#xff1a;深入体验Microsoft Edge浏览器一、Edge浏览器概述1.1 发…

从零开始搭建网站(第二天)

今天把之前的htmlcssjs项目迁移过来&#xff0c;直接使用tspiniavue3vite组合&#xff0c;搭建过程可以看从零开始搭建性能完备的网站-思路过程&#xff08;1&#xff09;_自己架设一个芯参数网站-CSDN博客。之后安装一下volar扩展。迁移过来使用Vue重构时发现之前使用的左右两…

C++从入门到精通——内部类和匿名类

内部类和匿名类 前言一、内部类的概念示例 二、内部类的特性三、匿名类的概念示例 四、匿名类的特性总结 前言 内部类是定义在另一个类内部的类&#xff0c;它可以访问外部类的私有成员。匿名类是没有名字的类&#xff0c;通常用于一次性使用的简单对象创建&#xff0c;可以直…

ubuntu20.04安装+ros-noetic安装+内网穿透frp

刷机后的系统安装 ubuntu20.04安装安装ros-noetic安装各种必要的插件安装vscode内网穿透连接实验室主机配置frpc和frps文件运行完成自动化部署免密登录linux的免密登录windows上的免密登录 内网穿透的参考链接&#xff1a;如何优雅地访问远程主机&#xff1f;SSH与frp内网穿透配…

【刷题篇】回溯算法(五)

文章目录 1、N皇后2、有效的数独3、解数独4、单词搜索5、黄金矿工 1、N皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你…