当前位置:   article > 正文

C++中的二分_c++二分

c++二分

二分是算法中比较基础简单的,但是边界值问题是二分问题比较头疼的

如果处理不好很容易会越界,或者死循环。

二分查找一个确定值(不考虑相同值的左右边界)

本二分查找采用搜索左闭右开的区间数组,所以 [l,r) = [l,r-1];

如果从下标1开始记录第一个数,那查找区间 [1,n+1] r=n(实际长度)+1 

或者[1,num.size],size包括了arr[0]的个数了 num.size=n+1

如果从下标0开始记录第一个数,那查找区间为 [0,n] 因为 arr[0]也记录也一个数,arr[n]没有记录

或者[0,num.size] 

  1. int l=1,r=num.size();
  2. int mid;
  3. int flag=1;
  4. while(l<r){
  5. mid=(l+r)/2;
  6. if(num[mid] == x)
  7. {
  8. flag=0;
  9. break;
  10. }
  11. else if(num[mid] > x)
  12. {
  13. r=mid;
  14. }
  15. else if(num[mid] < x)
  16. {
  17. l=mid+1;
  18. }
  19. }
  20. if(flag)
  21. {
  22. cout<<"0";
  23. }
  24. else
  25. {
  26. cout<<num[mid];
  27. }

或者

  1. int bina(int l ,int r,int x)
  2. {
  3. int mid;
  4. while(l<r){
  5. mid=(l+r)/2;
  6. if(num[mid] == x)
  7. {
  8. return mid;
  9. }
  10. else if(num[mid] > x)
  11. {
  12. r=mid;
  13. }
  14. else if(num[mid] < x)
  15. {
  16. l=mid+1;
  17. }
  18. }
  19. retuen -1;
  20. }

二分查找相同元素的边界值(左边界或者右边界)

如vector<int> num = {0,2,4,7,7,7,8,12,15,17,19,20,23,25};

需要查找最左边或者右边的7

查找相同元素的左边界值

  1. int l=0,r=num.size();
  2. int mid;
  3. while(l<r){
  4. mid=(l+r)/2;
  5. //cout<<l<<" "<<r<<" "<<mid<<endl;
  6. if(num[mid] == x)
  7. {
  8. r=mid;//如果找到相等值,向左收缩继续,将mid变成右边界开区间
  9. }
  10. else if(num[mid] > x)
  11. {
  12. r=mid;
  13. }
  14. else if(num[mid] < x)
  15. {
  16. l=mid+1;
  17. }
  18. }
  19. cout<<l<<" "<<num[l]<<endl;

查找相同元素的右边界值

  1. int l=1,r=num.size();
  2. int mid;
  3. while(l<r){
  4. mid=(l+r)/2;
  5. //cout<<l<<" "<<r<<" "<<mid<<endl;
  6. cout<<l<<" "<<r<<" "<<mid<<endl;
  7. if(num[mid] == x)
  8. {
  9. l=mid+1;//如果找到相等值,向右收缩继续,右边界值不变,左边界值(l+1,r]
  10. }
  11. else if(num[mid] > x)
  12. {
  13. r=mid;
  14. }
  15. else if(num[mid] < x)
  16. {
  17. l=mid+1;
  18. }
  19. }
  20. cout<<l-1<<" "<<num[l-1]<<endl;

查找右边界的时候。一定要注意,目标值为l-1,因为r一直大于目标值

如果找不到目标值,就默认返回比 目标值 第一个大的元素

c++<algorithm>中二分算法

lower_bound :

lower_bound(begin,end,目标值) ,从begin到end-1位置,二分查找等于目标值的下标,如果没有找到,就返回第一个比目标值大的元素,获取下标应在减去num,

int k = lower_bound(num,num+k,x) - num

upper_bound:

upper_bound(begin,end,目标值),从begin到end-1位置,二分查找第一个大于目标值的下标

注意:使用vector时,应该用迭代器,

auto it =upper_bound(num.begin(),num.end(),x)-num.begin()

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. using namespace std;
  5. vector<int> num = {0,2,4,7,7,7,8,12,15,17,19,20,23,25};
  6. // 1 2 3 4 5 6 7 8 9 10 11 12 13
  7. int numm[] = {0,2,7,7,7,8,9,10,12,12,15,16};
  8. // 0 1 2 3 4 5 6 7 8 9 10 11
  9. int main()
  10. {
  11. int x;
  12. cin>>x;
  13. int i = lower_bound(numm,numm+12,x)-numm;
  14. cout<<i<<" "<<numm[i]<<endl;
  15. auto pos=upper_bound(num.begin(),num.end(),x)-num.begin();
  16. cout<<num[pos];
  17. }

按从大到小排序返回第一个小于目标值的 下标
 int pos=lower_bound(num,num+n,查找值,greater<int>())-num;  //返回数组中第一个小于或等于被查数的值 
 iint pos=upper_bound(num,num+n,查找,greater<int>())-num;  //返回数组中第一个小于被查数的值 

二分查找例题

Problem - 1742E - Codeforces

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/348881
推荐阅读
相关标签
  

闽ICP备14008679号