当前位置:   article > 正文

【蓝桥杯知识点】二分查找(超超超详细,再也不会错啦)_scratch二分查找次数

scratch二分查找次数

        考完了计算机三级,蓝桥杯和数学建模的学习也要恢复常态啦!今天,我们来了解一种相对简单但容易出错的算法——二分查找。这里还有一些小方法让二分查找没有那么容易出错,开始学习吧啦啦啦!

PS: 文章主要参考:b站 一只会code的小金鱼 的视频(真的讲得超级超级详细!!!很适合大一没接触过算法的小白学习,而且up的声音也很好听很好听!!!墙裂推荐!)

 基本思路

 

如上图:

查找的对象是一个已经排列好顺序的数的序列,这里要想像一个不存在的红蓝边界,要找的那个数就是红蓝边界,为了找到那个数,先找头尾l和r(-1,n),再找一个中间值,即m=\frac{l+r}{2},如果m属于蓝色,那么头就变成m,如果属于红色尾就变成m,依次查找直到头+1=尾

  l                            I                                                     r   

初始:l指向蓝色区域,r指向红色区域

循环:l,r快速向红蓝边界靠近,保持lr颜色不变

时间复杂度: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

   主体:

  1. int l=0,r=9;
  2. while(l+1!=r)
  3. {
  4. int mid (l+r)/2;
  5. if(isblue(q[mid]))
  6. {
  7. l=mid;
  8. }
  9. else r=mid;
  10. if(arr[l]==5)
  11. {
  12. return r;
  13. }
  14. }

isblue:

  1. bool isblue(int x)
  2. {
  3. if(x<=5)
  4. return true;
  5. else
  6. return false
  7. }

 题目变形:

数组:     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了

  1. int l=-1,r=8;
  2. while(l+1!=r)
  3. {
  4. int mid (l+r)/2;
  5. if(isblue(q[mid]))
  6. {
  7. l=mid;
  8. }
  9. else r=mid;
  10. if(arr[l]==5)
  11. {
  12. return l;
  13. }
  14. }
  1. bool isblue(int x)
  2. {
  3. if(x<=5)
  4. return true;
  5. else
  6. return false
  7. }

例题 数的范围

题目:

 

答案:

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstring>
  4. using namespace std;
  5. const int N=100010;
  6. int n,q;
  7. int arr[N];
  8. //数组中的数是num,被询问数是x
  9. bool isBlue1(int num,int x)
  10. {
  11. if(num<x) return true;
  12. else return false;
  13. }
  14. //第一个二分查找的是 被询问数第一次出现的位置(下标)
  15. bool isBlue2(int num,int x)
  16. {
  17. if(num<=x) return true;
  18. else return false;
  19. }
  20. //第二个二分查找的是 被询问数最后一次出现的位置(下标)
  21. int binary_search1(int q[],int len,int x)
  22. {
  23. int l=-1,r=len;
  24. while(l+1<r)
  25. {
  26. int mid=(l+r)/2;
  27. if(isBlue1(q[mid],x))
  28. {
  29. l=mid;
  30. }
  31. else r=mid;
  32. }
  33. if(arr[r]==x) return r;
  34. else return -1;
  35. }
  36. int binary_search2(int q[],int len,int x)
  37. {
  38. int l=-1,r=len;
  39. while(l+1<r)
  40. {
  41. int mid=(l+r)/2;
  42. if(isBlue2(q[mid],x))
  43. {
  44. l=mid;
  45. }
  46. else r=mid;
  47. }
  48. if(arr[r]==x) return l;
  49. else return -1;
  50. }
  51. int main()
  52. {
  53. scanf("%d %d",&n,&q);
  54. for(int i=0;i<n;i++)
  55. {
  56. scanf("%d",&q[i]);
  57. }
  58. while(q--)
  59. {
  60. int x;
  61. scanf("%d",&x);
  62. int res1=binary_search1(arr,n,x);//查找数起始下标
  63. //优化:
  64. if(res1==-1)
  65. {
  66. printf("-1 -1\n");
  67. continue;
  68. }
  69. int res2=binary_search2(arr,n,x);//查找数终止下标
  70. }
  71. printf("%d %d\n",res1,res2);
  72. return 0;
  73. }

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

闽ICP备14008679号