二分查找学习笔记

一、简介:

1、何为二分?

        二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

2、怎样能二分?

  • 是一个有序数列(俗称符合单调性)
  • 必须是按照关键字大小进行排序

3、如何二分?

1.思路:

假设我们比较的有序数列有三个数,我们比较一个元素的值和数组中间位置的元素的值进行比较,如果比中间的元素大,则在有序数组的后半部分进行查找;如果中间位置的元素的值小,则跟有序数组的前半部分进行比较;如果相等,则找到了比较元素的位置. 

2.过程:

(1)设置查找区间:

int l=1.r=n;

(2)判断[left,right]是否成立,否则查找失败,返回-1,是则继续执行(3);

(3)取中间mid=l+r>>1,比较a[mid]与x(要找的数),得以下3情况:

        1. 若 x < a[mid],则right = mid - 1;查找在左半区间进行,转(2);

        2. 若 x > a[mid],则left = mid + 1;查找在右半区间进行,转(2);

        3. 若 x = a[mid],则查找成功,返回mid的值;

3.实现(递归与循环):

int ef(int l, int r, int x) {
    if(l>=r) return -1;
	int mid=l+r>>1;
	if (x<a[mid]) {
		return ef(l,mid-1,x);
	}
	else if (x>a[mid]) {
		return ef(mid+1,r,x);
	}
	else {
		return mid;
	}
}
int ef(int l,int r,int x){
    while(l<r){
        int mid=l+r>>1;
        if(a[mid]<x) l=mid+1;
        else if(a[mid]>x) r=mid-1;
        else return mid;
    }
    return -1;
}

二分之重,在于 l 和 r 还有 mid 在每一次比较之后应该怎样的变 。

4.图示

        二分简直是遥遥领先啊。

二、例题:

何老板的淘宝店icon-default.png?t=N7T8http://oi.nks.edu.cn:19360/zh/Problem/Details?cid=2772&tid=A

        若数据加强,用桶定然会MLE,故这题应该用二分,先将商品价格由小到大排序,再在数组中用二分查找每位顾客要买的商品有没有。若有,则将ans加上数量乘单价。

核心代码:

bool erfen(long long l,long long r,long long x){
	long long mid=(r+l)/2;
    while(l<=r){
    	mid=(r+l)/2;
    	if(a[mid]==x){
    		return true;
		}  
    	else if (a[mid]<x) {
    		l=mid+1;
		} 
    	else if(a[mid]>x){
    		r=mid-1;
		}   
	}
	return false;
}

人数统计icon-default.png?t=N7T8http://oi.nks.edu.cn:19360/zh/Problem/Details?cid=2772&tid=B

        对于每个a[i](排序后),查找最后一个小于等于他的数(下标)。紧接着判断他与要找的数是否相同,若不相同,则说明序列中并没有此元素,若相同,则查找最后一个小于等于他+1的数(下标)(也就是第一个大于等于他的数),将两数组下标相减,可得k的个数。另外,如果输入数字不在查找范围之内,直接输出0即可。

核心代码:

	for(int i=1;i<=m;i++){
		scanf("%d",&x);
		if(x<a[1]){
			printf("0\n");
			continue;
		}
		if(x>a[n]){
			printf("0\n");
			continue;
		}
		cnt_l=rf(x,n);
		if(a[cnt_l]!=x){
			printf("0\n");
			continue;
		}
		if(x==a[n]){
			a[n+1]=x+1;
			cnt_r=rf(x+1,n+1);
		}
		else
		cnt_r=rf(x+1,n);
		printf("%d\n",cnt_r-cnt_l);
		a[n+1]=0; 
	}

三、总结

        私以为,二分的金随,就在于“边界”。l是等于mid+1还是mid?r是等于mid-1还是mid?a[mid]于x的比较是否取等?l是<r还是<=r?综上所述,我们可以将模板背过。

 

int rf(int m,int y){
	l=1,r=y;
	while(l<r){
		int k=(l+r)/2;
		if(a[k]<m){
			l=k+1;
		}
		else r=k;
	}
	return l;
} 

 完~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值