算法:C++实现二分查找

9 篇文章 0 订阅
7 篇文章 0 订阅

事出有因,昨晚内推笔试题,采用遍历的方式提示耗时,由于系统原因(忍不住再次吐槽一下考试系统,估计是单线程队列模式),本地测试通过但是系统提交不上去,好不容易提交上去发现没通过全部的测试用例,当考虑用二分查找方式实现时时间已耗完。

题目:新兵入队,编号从1开始依次递增(10个人的话编号是1-10),共分成N个队伍,指定每个队伍中的人数并分配新兵(按照编号顺序),然后随机选取Q个测试qi(i=1-Q),指出编号为qi的新兵在哪一组。举例:新兵分为五组N=5,从第一组到第五组的人数分别为2,7,3,4,9。测试三个数据Q=3,编号为1的在第一组,编号为25的新兵在第五组,编号为11的新兵在第3组。
测试用例:
输入
5
2 7 3 4 9
3
1 25 11

输出:
1
5
3

思路:开始最先想到的是先记录每个组的编号的大小区间(例如测试用的第二组区间为3-9),然后根据每个编号,遍历每个组数判断是否在该组的区间内,如果在就输出,不在继续往后找。这种暴力的方式在本地编译没有问题,但是考试系统就出现了问题。由于编号是有序的,且按照有序的方式进行分组,满足二分查找的前提,我们可以记录当前组的最大编号形成一个序列(上述五个组分别为2 9 12 16 25),然后查找大于测试qi的最小数所在的组就解决了问题。重点是本来想自己实现二分查找,发现STL中已经集成了相关类型的函数模板lower_bound(),先实现一下:

#include<iostream>
#include<vector>
#include<algorithm>
int main(){
    long long num;
    std::cin>>num;
    long long count=0;
    std::vector<int> groups(num);
    for(long long i=0;i<num;++i){
        long long temp;
        std::cin>>temp;
        groups[i]=count+temp;
        count+=temp;
    }
    long long q;
    std::cin>>q;
    long long qi;
    for(long long i=0;i<q;++i){
        std::cin>>qi;
        long long mid=std::lower_bound(groups.begin(),groups.end(),qi)-groups.begin();
        std::cout<<mid+1<<std::endl;

    }
    return 0;
}

附上常见的二分查找(递归和非递归):

递归:
int find(vector<int>const &vec,int start,int end,int value){
    if(start>end){
      return -1;
    }
    int mid=(start+end)>>1;
    if(vec[mid]==value){
      return mid;
    }
    if(vec[mid]<value){
      return find(vec,mid+1,end,value);
    }
    if(vec[mid]>value){
      return find(vec,start,mid-1,value);
    }
}
非递归
int find(vector<int>const &vec,int start,int end,int value){
    while(start<=end){
      int mid=(start+end)>>1;
      if(vec[mid]==value){
        break;
      }
      if(vec[mid]<value){
        start=mid+1;
      }
      else{
        end=mid-1;
      }
    }
    return -1;
}

有关STL二分查找的算法,可以参见另一篇博客STL二分查找算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值