Loading

浅谈两种二分模板

前言

之前看y总的视频,在二分那块y总给了两个模板,但对于这两个模板的区别我并没有一个清晰的认识。后来在二分的专项训练中,两个模板对于对于部分题来说是通用的,但是对于少数题目来说只能用其中的一个,这里我对两个模板的不同性质做了一个简单的测试。

第一个模板

int bsearch_1(int x){
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(q[mid] >= x) r = mid;
        else l = mid + 1;
    }
    
    return l;
}

第二个模板

int bsearch_2(int x){
    int l = 0, r = n - 1;
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(q[mid] <= x) l = mid;
        else r = mid - 1;
    }
    
    return l;
}

测试

测试点为两个数组:1 2 2 5 5 7(6个元素)和1 2 2 4 6 6 6 8 9(9个元素)

测试代码

/*
*	n是数组的长度,k是要查找的值
*/
#include <iostream>
using namespace std;
int n, k;
int q[100000];

int bsearch_1(int x){
    int l = 0,r = n - 1;
    while(l < r){
        int mid = l + r >> 1;
        if(q[mid] >= x) r = mid;
        else l = mid + 1;
    }
    
    return l;
}

int bsearch_2(int x){
    int l = 0, r = n - 1;
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(q[mid] <= x) l = mid;
        else r = mid - 1;
    }
    
      return l;
}

int main(){
	cin >> n >> k;
	for(int i = 0; i < n; i++) cin >> q[i];
	
	cout << bsearch_1(k) << ' ' << bsearch_2(k) << endl;
	
	return 0;
}

第一类测试:查找连续具有重复元素的数字

对于两个测试点,分别选择数字26作为查找的元素,输出结果如下

测试元素 2 5
bsearch_1输出的下标 1 4
bsearch_2输出的下标 2 6
结论:

通过测试结果我们可以发现,查找有重复元素的数字,bsearch_1返回的是第一个元素的下标,而bsearch_2返回的是最后一个元素的下标。

第二类测试:查找数组中不存在的某个值

  • 对于查找一个大于数组中最大元素的值或一个小于数组中最小元素的值,这里可以简单带过,两个模板都返回了数组的最小下标和最大下标。
  • 对于两个测试点,分别选择35作为查找的元素,输出结果如下
测试元素 2 5
bsearch_1输出的下标 3(对应元素5) 4(对应元素6)
bsearch_2输出的下标 2(对应元素2) 3(对应元素2)
结论
  • 对于bsearch_1,它返回了第一个大于查找元素的下标
  • 对于bsearch_2,它返回了最后一个小于查找元素的的下标

小结

对于bsearch_1:它会返回第一个大于等于查找元素的下标,等同于lower_bound()

对于bsearch_2:类似upper_bound() - 1

  • 当查找元素存在时,会返回等于查找数字的元素的最大下标。
  • 如果查找元素不存在,会返回小于查找数字的最大元素的最大下标

两种模板在具体例题的应用和区别

未完待续,挖个坑

posted @ 2021-01-28 17:13  Frank_Ou  阅读(574)  评论(0编辑  收藏  举报