赞
踩
考完了计算机三级,蓝桥杯和数学建模的学习也要恢复常态啦!今天,我们来了解一种相对简单但容易出错的算法——二分查找。这里还有一些小方法让二分查找没有那么容易出错,开始学习吧啦啦啦!
PS: 文章主要参考:b站 一只会code的小金鱼 的视频(真的讲得超级超级详细!!!很适合大一没接触过算法的小白学习,而且up的声音也很好听很好听!!!墙裂推荐!)
如上图:
查找的对象是一个已经排列好顺序的数的序列,这里要想像一个不存在的红蓝边界,要找的那个数就是红蓝边界,为了找到那个数,先找头尾l和r(-1,n),再找一个中间值,即m=,如果m属于蓝色,那么头就变成m,如果属于红色,尾就变成m,依次查找直到头+1=尾
l I r
初始:l指向蓝色区域,r指向红色区域
循环:l,r快速向红蓝边界靠近,保持l,r颜色不变
时间复杂度:O(log n)
注意:l初始位置为-1,r的初始位置为N,防止出现如下情况:
5 5 8 9
在上面的数组中查找<=4的数出现的位置,如果l初始=0,就会出现错误
一定要让l初始在蓝,r初始在红!
I 5 5 8 9
l初始位置为-1,r的初始位置为N,则黄色即为边界,程序马上退出循环体
核心就是这段伪代码啦:
注意:Isblue中,blue的判断条件 是blue的条件,如<5(下图例1)
这些查找都可以用c++中 的库函数,但二分题型很多,还是掌握根本比较好
数组: 3 4 4 5 5 5 6 7
分析红蓝条件,找到边界,找到第一个>5的元素的下标
数组: 3 4 4 5 5 5 I 6 7
下标: 1 2 3 4 5 6 7 8
主体:
- int l=0,r=9;
- while(l+1!=r)
- {
- int mid (l+r)/2;
- if(isblue(q[mid]))
- {
- l=mid;
- }
- else r=mid;
- if(arr[l]==5)
- {
- return r;
- }
- }
isblue:
- bool isblue(int x)
- {
- if(x<=5)
- return true;
- else
- return false
- }
数组: 3 4 4 5 5 5 6 7
分析红蓝条件,找到边界,找到第一个<=5的元素的下标
数组: 3 4 4 5 5 5 I 6 7
下标: 0 1 2 3 4 5 6 7 //注意下标变成1了
- int l=-1,r=8;
- while(l+1!=r)
- {
- int mid (l+r)/2;
- if(isblue(q[mid]))
- {
- l=mid;
- }
- else r=mid;
- if(arr[l]==5)
- {
- return l;
- }
- }
- bool isblue(int x)
- {
- if(x<=5)
- return true;
- else
- return false
- }
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- using namespace std;
-
- const int N=100010;
-
- int n,q;
- int arr[N];
-
- //数组中的数是num,被询问数是x
- bool isBlue1(int num,int x)
- {
- if(num<x) return true;
- else return false;
- }
-
- //第一个二分查找的是 被询问数第一次出现的位置(下标)
- bool isBlue2(int num,int x)
- {
- if(num<=x) return true;
- else return false;
- }
-
- //第二个二分查找的是 被询问数最后一次出现的位置(下标)
- int binary_search1(int q[],int len,int x)
- {
- int l=-1,r=len;
- while(l+1<r)
- {
- int mid=(l+r)/2;
- if(isBlue1(q[mid],x))
- {
- l=mid;
- }
- else r=mid;
- }
- if(arr[r]==x) return r;
- else return -1;
- }
-
- int binary_search2(int q[],int len,int x)
- {
- int l=-1,r=len;
- while(l+1<r)
- {
- int mid=(l+r)/2;
- if(isBlue2(q[mid],x))
- {
- l=mid;
- }
- else r=mid;
- }
- if(arr[r]==x) return l;
- else return -1;
- }
-
-
-
- int main()
- {
- scanf("%d %d",&n,&q);
- for(int i=0;i<n;i++)
- {
- scanf("%d",&q[i]);
- }
-
- while(q--)
- {
- int x;
- scanf("%d",&x);
- int res1=binary_search1(arr,n,x);//查找数起始下标
- //优化:
- if(res1==-1)
- {
- printf("-1 -1\n");
- continue;
- }
- int res2=binary_search2(arr,n,x);//查找数终止下标
- }
-
- printf("%d %d\n",res1,res2);
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。