二分查找知识点及练习题

news2024/11/16 9:56:20

知识点讲解

一、没有相同元素查找

请在一个有序递增数组中(不存在相同元素),采用二分查找,找出值x的位置,如果x在数组中不存在,请输出-1!

 输入格式

 第一行,一个整数n,代表数组元素个数(n <= 600000)

第二行,n个数,代表数组的n个递增元素(1<=数组元素值<=2000000)

 第三行,一个整数x,代表要查找的数(0<=x<=2000000)

输出格式

按题意输出位置或者-1。

输入/输出例子1

输入:

10

1 3 5 7 9 11 13 15 17 19

3

输出:

2

【分析】:当我们要从一个序列中查找一个元素的时候,最快想到的方法就是顺序查找法(即:从前到后依次查找)。但这种方法过于无脑,就是暴力的把每个元素都排查一遍。元素个数少的时候还行,一旦元素个数多起来,效率非常低下。

分查找法也称折半查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log2n)完成查找任务。

它的基本思想是,先把n个元素从小到大排序,然后取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如果x<a[n/2],则我们只要在数组a的左半部分继续搜索x。如果x>a[n/2],则我们只要在数组a的右半部分继续搜索x,直到查找成功或查找完毕为止。

以下是二分查找的查找过程图示:

12.jpg

23.jpg

二分查找的算法框架一如下:

left=1;right=n;

while(left<=right)

{

   mid=(left+right) / 2;

   if (x==a[mid]){ printf("%d",mid)}//查找成功,输出mid的值并结束;

   if (x>a[mid]) left=mid+1;//往数组的右边找

   if (x<a[mid]) right=mid-1;//往数组的左边找

}
printf("查找不成功")//输出“查找不成功”

在查找过程中我们每次把查找的范围缩小了一半,在最坏情况下查找log2n次就可以得到结果。

注意:

1.二分查找是在数据有序的情况下才能完成,即进行二分查找前数据必须先排序。上述框架是以数据已从小到大排序为前提条件的。

2.这里可能解的范围为[left,rigth],当x>a[mid]时,x如果存在的话应该是在数组的[mid+1,right]中,此时的left改为mid+1,而不是mid;同理,当x<a[mid]时,x如果存在的话应该在数组的[left,mid-1]里,此时的right应该改为mid-1,而不是mid。

41.png

42.png

43.png

二分查找的算法框架二如下:

left=0;right=n+1;

while(left+1<right)

{

 mid=(left+right) / 2;

 if (x==a[mid]){ printf("%d",mid);}//查找成功,输出mid的值并结束;

 if (x>a[mid]) left=mid;//往数组的右边找

 if (x<a[mid]) right=mid;//往数组的左边找

}

printf("查找不成功");//输出“查找不成功”

二、有相同元素的查找

1、求左侧边界:

这样就引申出一个问题:如何二分查找求左侧边界。当查找的数字v存在时,得到它出现的第一个位置,假如不存在,就得到比它大的第一个数的位置。

这样只要把二分查找修改一下:

为了查找方便,我们在数组a[0]处插入一个最小的数-1,在a[n+1]处插入一个无穷大数,left指向0,right指向n+1,这样解空间为(left,right]。

1、 情况a[mid]>=v时:right=mid(至少已经找到一个,或者mid可能已经是比v大的数中最小的一个,或者左边可能还有比v大的,因此区间变成(left,mid]。)

2、 情况a[mid]<v时;left=mid,也就是解只可能在右边。

例如:

-1 2 3 5 6 7 7 8  10000000 中查找v=7

第一轮:left=0,right=9,解空间为(0,9]那么mid=(0+9)/2=4,因为a[4]=6<7,那么left=mid=4,解空间应该是(4,9]。

第二轮left=4,right=9, mid=(4+9)/2=6 ,因为a[6]=7==7,那么right=6,也就是解空间为(4,6]。

第三轮 left=4,right=6, mid=(4+6)/2=5 ,因为a[5]=7==7,那么right=5,也就是解空间为(4,5]。

因为解空间只有一个解,所以解为下标5,所以left+1==right为程序结束条件。

【求下界核心程序如下】:

a[n+1]=1000000000;

a[0]=-1;

int findleft(int left,int right,int value)//调用时left=0,right=n+1

{

while(left+1<right)  //如果解区间不止一个,那么继续二分

{

   int mid=(left+right)/2;  //取中间值

   if(a[mid]>=value)//如果找到一个等于或者大于value的数,解空间为(left,mid]

  right=mid;

else

   left=mid; //如果找到一个小于value的数,解空间为(mid,right]

}

return right;

}

2、求右侧边界

如何二分查找求右侧边界。当查找的数字v存在时,得到比它大的第一个数的位置。

方法如下:

为了查找方便,我们在数组a[0]处插入一个最小的数-1,在a[n+1]处插入一个无穷大数,left指向0,right指向n+1,这样解空间为(left,right]。

1、 情况a[mid]>v时:right=mid(至少已经找到一个,或者mid可能已经是比v大的数中最小的一个,或者而左边可能还有比v大的,因此区间变成(left,mid]。)

2、 情况a[mid]<=v时;left=mid,也就是解只可能在右边。

【求上界核心程序如下】:

a[n+1]=1000000000;

a[0]=-1;

int findright(int left,int right,int value)//调用时left=0,right=n+1

{

while(left+1<right) //如果解区间不止一个,那么继续二分查找

{

   int mid=(left+right)/2;

   if(a[mid]<=value)//找到一个小于或者等于value的数,解空间为(mid,right)

  left=mid;

else

  right=mid; //如果找到一个大于value的数,解空间为(left,mid)

}

return right;

}

拓展:另外一种二分查找形式找左侧和右侧:

根据c++的整除是求下界,那么两个相邻的数求平均数等于较小的数,也就是当求区间解时,当左区间不能满足要求时,可以让left=mid+1,跳出条件变为L<R,也就是解空间为(L,R]。

找左侧核心程序如下:

int L=0,R=n+1,mid;

while(L<R)

{

   mid=(L+R)/2;

   if(a[mid]<x)

       L=mid+1;

   else

      R=mid;

}

if(a[R]==x) printf("%d ",R);

else printf("-1 ");

找右侧核心程序如下:

int L=1,R=n+1,mid;

while(L<R)

{

    mid=(L+R)/2;

     if(a[mid]<= x)

        L=mid+1;

    else

        R=mid;

   

}

if(a[L-1]==x) printf("%d ",L-1);

else printf("-1 ");

讲完知识点,我们来看看几道习题

习题部分

进击的河流

有一个铁人三项运动员,他的弱点是就是游泳,正好他家旁边有n条流速不同的河流,他想锻炼m天。
在这m天中,他每天都有不同的体力,他只能在流速小于他体力的河流里游,不然他就会被冲到太平洋(?!!!!!!)。
他想知道每天他能在多少条河里游泳。

输入格式

第一行:n(n<=10^6)

第二行:n个数,分别表示n条河流的流速

第三行:m(m<=10^6)

接下来有m行,分别表示m天中运动员不同的体力

输出格式

m行,分别表示运动员m天里每天他能在多少条河里游泳

输入/输出例子

输入:

10
1 1 1 2 2 2 2 3 4 4
5
3
2
5
4
1

输出:

7
3
10
8
0

代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,a[10000005],x;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    cin>>k;
    while(k--){
        scanf("%d",&x);
        int l=0,r=n+1,m=0;
        while(l+1<r)
        {
            m=(l+r)/2;
            if(a[m]<x)l=m;
            else r=m;
        }
        cout<<r-1<<"\n";
    }
    
    return 0;
}

 生死狙击

小飞最近迷上了一个叫生死狙击的游戏。不过他的技术并不好,假设他的战斗力是•x。不过,他的战斗力是由心情来定的,每天都不同。现有一群(1<=n<=100000)也是玩生死狙击的朋友,他们也有战斗力。小飞想找一些比自己强的人玩,提高自己的战斗力,如:小烨,小祖,小明等。
小飞一共玩了m天,假设其他人的战斗力不变。问:小飞每天可以找到多少比自己强的人。

输入格式

第一行输入一个n,表示有n个朋友;(1<=n<=100000)
第二行输入n个朋友的战斗力;每个朋友战斗力不超过longint;(已有序);
第三行输入一个m,表示有m天;(1<=m<=100000)
接下来m行,表示小飞每天的战斗力;小飞战斗力不超过longint;

输出格式

共m行,每一行小飞每天找到的人数;

输入/输出例子

输入:

5
1 1 3 5 5
3
0
2
5

输出:

5
3
0
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,k,a[10000005],x;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    cin>>k;
    while(k--){
        scanf("%lld",&x);
        long long l=0,r=n+1;
        while(l+1<r){
            long long m=(l+r)/2;
            if(x>=a[m])l=m;
            else r=m;
        }
        printf("%lld\n",n-r+1);
    }
    return 0;
}

选人

在一条坐标轴上,有N头奶牛,第i头奶牛的位置是Xi。FJ现在要选出三头奶牛去比赛,不妨假设选择了奶牛a,b,c。那么必须要满足:

1、Xa < Xb < Xc。

2、 Xb-Xa <= Xc - Xb <= 2 * (Xb - Xa)。

你的任务是计算,FJ总共有多少种不同的选择?

输入格式

第一行,一个整数N。 3 <= N <= 1000。 接下来有N行,第i行是整数Xi。

输出格式

一个整数。

输入/输出例子

输入:

5 
3 
1 
10 
7 
4

输出:

4

样例解释

可以有4种不同的选择,每种选择对应的3头奶牛的坐标是: {1,3,7} {1,4,7} {4,7,10} {1,4,10}

代码:
#include<bits/stdc++.h>
using namespace std;
long long n,s,q[10000000],t,m,ans,ans2,l,r;
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&q[i]);
    sort(q+1,q+1+n);
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int l=0,r=n+1,m;
            while(l+1<r)
            {
                m=(l+r)/2;
                if(q[j]-q[i]>q[m]-q[j])l=m;
                else r=m;
            }
            ans=l;
            l=0,r=n+1;
            while(l+1<r)
            {
                m=(l+r)/2;
                if(q[m]-q[j]>2*(q[j]-q[i]))r=m;
                else l=m;
            }
            ans2=l;
            t+=ans2-ans;
        }
    }
    cout<<t;
    return 0;
}

能不能留下关注和点赞........

安慰一下啥也不会的小学生..........

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

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

相关文章

DevOps(十二)Jenkins实战之Web发布到远程服务器

前面两篇博文介绍了怎么将django开发的web应用推送到gitlab源码仓库&#xff0c;然后jenkins服务器从gitlab仓库拉下来&#xff0c;布署到jenkins服务器上&#xff0c;并用supervisor进行进程管理&#xff0c;保证web应用一直能正常运行&#xff0c;今天我们继续优化&#xff0…

政安晨:【深度学习神经网络基础】(十三)—— 卷积神经网络

目录 概述 LeNet-5 卷积层 最大池层 稠密层 针对MNIST数据集的卷积神经网络 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎…

绿色便携方式安装apache+mysql+tomcat+php集成环境并提供控制面板

绿色便携方式安装带控制面板的ApacheMariaDBTomcatPHP集成环境 目录 绿色便携方式安装带控制面板的ApacheMariaDBTomcatPHP集成环境[TOC](目录) 前言一、XAMPP二、安装和使用1.安装2.使用 三、可能的错误1、检查端口占用2、修改端口 前言 安装集成环境往往配置复杂&#xff0c…

Gradio 最快创建Web 界面部署到服务器并演示机器学习模型,本文提供教学案例以及部署方法,避免使用繁琐的django

最近学习hugging face里面的物体检测模型&#xff0c;发现一个方便快捷的工具&#xff01; Gradio 是通过友好的 Web 界面演示机器学习模型的最快方式&#xff0c;以便任何人都可以在任何地方使用它&#xff01; 一、核心优势&#xff1a; 使用这个开发这种演示机器学习模型的…

leetcode-比较版本号-88

题目要求 思路 1.因为字符串比较大小不方便&#xff0c;并且因为需要去掉前导的0&#xff0c;这个0我们并不知道有几个&#xff0c;将字符串转换为数字刚好能避免。 2.当判断到符号位的时候加加&#xff0c;跳过符号位。 3.判断数字大小&#xff0c;来决定版本号大小 4.核心代…

LabVIEW和MES系统的智能化车间数据对接

LabVIEW和MES系统的智能化车间数据对接 随着工业4.0时代的到来&#xff0c;智能制造成为推动制造业高质量发展的重要手段。其中&#xff0c;数字化车间作为智能制造的重要组成部分&#xff0c;其设计与实现至关重要。在数字化车间环境下&#xff0c;如何利用LabVIEW软件与MES系…

2024 年 Rust 开发者路线图

Rust 近年来因其对性能、安全性和并发性的关注而广受欢迎。作为一名开发人员&#xff0c;掌握 Rust 可以为各种机会打开大门&#xff0c;包括 Web 开发。 在 github 上发现了这个优秀的路线图&#xff0c;由 Anshul Goyal 创建&#xff0c;它提供了一条全面的路径&#xff0c;概…

第十五届蓝桥杯省赛第二场C/C++B组A题【进制】题解

解题思路 按照题意进行模拟&#xff0c;计算 x x x 的 b b b 进制过程中&#xff0c;若出现余数大于 9 9 9&#xff0c;则说明 x x x 的 b b b 进制一定要用字母进行表示。 #include <iostream> #include <cstring> #include <algorithm> #include &l…

大数据Hive中的UDF:自定义数据处理的利器(上)

文章目录 1. 前言2. UDF与宏及静态表的对比3. 深入理解UDF4. 实现自定义UDF 1. 前言 在大数据技术栈中&#xff0c;Apache Hive 扮演着数据仓库的关键角色&#xff0c;它提供了丰富的数据操作功能&#xff0c;并通过类似于 SQL 的 HiveQL 语言简化了对 Hadoop 数据的处理。然而…

configure: error: library ‘crypto‘ is required for OpenSSL

1、执行命令./configure --prefix/usr/local/pgsql/postgresql-14.2 --with-openssl 报错configure: error: library crypto is required for OpenSSL 2、解决办法 yum install openssl openssl-devel

Kafka 3.x.x 入门到精通(02)——对标尚硅谷Kafka教程

Kafka 3.x.x 入门到精通&#xff08;02&#xff09;——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.1.1 解压文件2.1.2 安装ZooKeeper2.1.3 安装Kafka2.1.4 封装启动脚本 2.2 集群启动2.2.1 相关概念2.2.1.1 代理&#xff1a;Broker2.2.1.2 控制器&#xff1a;Controller …

爬虫学习笔记-数美验证

测试网址&#xff1a;智能验证码体验_图片验证码_数美科技数美科技智能验证码在线体验&#xff0c;智能识别风险用户级别&#xff0c;自行切换智能验证码难度及类型&#xff0c;提供滑动、拼图、点选、数字、动态等多种智能验证码服务&#xff0c;精准拦截机器行为。https://ww…

AIGC-stable-diffusion(文本生成图片)+PaddleHub/HuggingFace

功能 stable-diffusion(文本生成图片)PaddleHub&#xff0c;HuggingFace两种调用方式 PaddleHub 环境 pip install paddlepaddle-gpu pip install paddlehub 代码 from PIL import Image import paddlehub as hub module hub.Module(namestable_diffusion)## 保存在demo…

智能驾驶+网络安全

在智能驾驶场景下&#xff0c;安全问题一直是一个持续热点。 针对车机模块不被黑客利用Linux的漏洞攻击&#xff0c;可以采取以下几种方式来提高安全性&#xff1a; 安全设计和防护&#xff1a;在设计车机模块时&#xff0c;需要考虑安全性&#xff0c;并采取相应的安全防护措施…

5 个有用的 Linux Shell 转义序列

目录 ⛳️推荐 前言          1、退格符 2、换行符 3、换页符 4、制表符 5、Unicode ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 前言          如何在你的…

ArcGIS无法开始编辑TIN!开始编辑TIN显示灰色

ArcGIS无法开始编辑TIN&#xff01;开始编辑TIN显示灰色&#xff1f; 解决方案&#xff01; 1、确认自定义——扩展模块中空间分析、3D分析模块勾选。 2、确认以上后&#xff0c;还是不能编辑的话&#xff0c;我们可以调出 3D分析分析工具条&#xff0c;你就会发现。TIN编辑工…

c++初阶-----STL---vector

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

Git 版本控制:构建高效协作和开发流程的最佳实践

引言 版本控制是开发中不可或缺的一部分&#xff0c;他允许多人同时协作&#xff0c;通过记录每一次代码的变更&#xff0c;帮助开发者理解何时、为什么以及谁做了修改。这不仅有助于错误追踪和功能回溯&#xff0c;还使得团队能够并行工作&#xff0c;通过分支管理实现功能的…

计算机网络4——网络层2

文章目录 一、地址解析协议ARP二、IP数据报格式1、IP 数据报首部的固定部分中的各字段2、IP 数据报首部的可变部分 三、IP 层转发分组的过程1、流程2、案例分析3、最长前缀匹配4、分组转发算法5、使用二叉线索查找转发表 一、地址解析协议ARP 在实际应用中&#xff0c;我们经常…

FeignClient注入错误,IDemoClient that could not be found.

问题描述&#xff1a; 项目引入openFeign ,调用FeignClient提示&#xff1a; Field demoClient in com.demo2.controller.DemoController required a bean of type com.demo.feign.IDemoClient that could not be found. The injection point has the following annotations…