zoukankan      html  css  js  c++  java
  • binary_search算法

    计算机科学中,折半搜索英语:half-interval search),也称二分查找算法binary search)、二分搜索法二分搜索二分探索,是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

    递归版:

     1 int binary_search(const int arr[],int start,int end,int key)
     2 {
     3     if(start>end)
     4         return -1;
     5     int mid=start+(end-start)/2;
     6     if(arr[mid]>key)
     7         return binary_search(arr,start,mid-1,key);
     8     if(arr[mid]<key)
     9         return binary_search(arr,mid+1,end,key);
    10     return mid;
    11 }
    View Code

    循环版:

     1 int binary_search(const int arr[],int start,int end,int key)
     2 {
     3     while(start<=end)
     4     {
     5         int mid=start+(end-start)/2;
     6         if(arr[mid]>key)
     7             end=mid-1;
     8         else if(arr[mid]<key)
     9             start=mid+1;
    10         else
    11             return mid;
    12     }
    13     return -1
    14 }
    View Code

    uva,10077 结构体单次打表的妙处

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 
     6 struct fraction
     7 {
     8     int x;
     9     int y;
    10 };
    11 
    12 int main()
    13 {
    14     int m,n;
    15     while(scanf("%d %d",&m,&n))
    16     {
    17         if(m==1 && n==1) break;
    18         fraction L={0,1},M={1,1},R={1,0};
    19         while(1)
    20         {
    21         long double t1=(long double)m/n,t2=(long double)M.x/M.y;
    22         if(t1<t2)
    23         {
    24             printf("L");
    25             R=M;
    26             M.x+=L.x;
    27             M.y+=L.y;
    28         }
    29         else if(t1>t2)
    30         {
    31             printf("R");
    32             L=M;
    33             M.x+=R.x;
    34             M.y+=R.y;
    35         }
    36         else
    37         {
    38             printf("
    ");
    39             break;
    40         }
    41         }
    42     }
    43     return 0;
    44 }
    View Code

    uva,10706

    //注意1-9之后10算两位数字,所以分数组的时候不是等差。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cctype>
     5 #include <string.h>
     6 #define maxn 2147483647
     7 using namespace std;
     8 
     9 int K;
    10 char b[1000000];
    11 long long sum[100000];
    12 
    13 int pan(int x)
    14 {
    15     int n=0;
    16     while(x)
    17     {
    18         x/=10;
    19         n++;
    20     }
    21     return n;
    22 }
    23 
    24 void init()
    25 {
    26     int a;
    27     K=sqrt(maxn)+1;
    28     int j=1;
    29     for(int i=1;i<=K;i++)
    30     {
    31         sprintf(&b[j],"%d",i);
    32         while(isdigit(b[j]))
    33             j++;
    34     }
    35     a=sum[0]=0;
    36     for(int i=1;i<=K;i++)
    37     {
    38         a+=pan(i);
    39         sum[i]=sum[i-1];
    40         sum[i]+=a;
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     int min,max,mid,k;
    47     init();
    48     int t,i;
    49     scanf("%d",&t);
    50     while(t--)
    51     {
    52         min=0;max=K;
    53         scanf("%d",&i);
    54         while(1)
    55         {
    56             mid=min+(max-min)/2;
    57             if(mid==min)
    58                 break;
    59             if(sum[mid]>=i)
    60                 max=mid;
    61             else
    62                 min=mid;
    63         }
    64         i-=sum[mid];
    65         printf("%c
    ",b[i]);
    66     }
    67     return 0;
    68 }
    View Code

    HDU,4282 具体详解

    //这类型题目确定两个值,二分搜索第三个。学会确定上下限。z<32,x,y<2^15

     1 #include <iostream>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 typedef long long ll;
     6 
     7 int ans,k;
     8 
     9 ll Pow(ll x,ll y)
    10 {
    11     long long tmp=x;
    12     for(long long i=1;i<y;i++)
    13         x*=tmp;
    14     return x;
    15 }
    16 
    17 void solve()
    18 {
    19     ans=0;
    20     ll mid,l,r,tmp;
    21     for(int z=2;z<32;z++)
    22     {
    23         for(int x=1;x<50000;x++)
    24         {
    25             if(Pow(x,z)>=k/2) break;
    26             l=x+1;r=50000;
    27             while(l<=r)
    28             {
    29             mid=(l+r)>>1;
    30             tmp=Pow(x,z)+Pow(mid,z)+x*mid*z;
    31             if(tmp==k)
    32             {
    33                 ans++;
    34                 break;
    35             }
    36             else if(tmp>k || tmp<0)
    37                 r=mid-1;
    38             else
    39                 l=mid+1;
    40             }
    41             
    42         }
    43     }
    44     printf("%d
    ",ans);
    45 }
    46 
    47 int main()
    48 {
    49     while(scanf("%d",&k) && k)
    50     {
    51         solve();
    52     }
    53     return 0;
    54 }
    View Code

    使用binary_search的思想:找到left  和right分别是什么  具体详解

    uva,11413

     1 #include <cstdio>
     2 
     3 using namespace std;
     4 
     5 int M,N;
     6 int n[1000001];
     7 
     8 int main()
     9 {
    10     while(scanf("%d %d",&M,&N)!=EOF)
    11     {
    12         int left=0,right=0,mid;
    13         for(int i=0;i<M;i++)
    14         {
    15             scanf("%d",&n[i]);
    16             if(n[i]>left) left=n[i];
    17             right+=n[i];
    18         }
    19         
    20         while(left<right)
    21         {
    22             mid=(left+right)>>1;
    23             int amount=0,sum=0;
    24             for(int i=0;i<M;i++)
    25             {
    26                 sum+=n[i];
    27                 if(sum>mid)
    28                 {
    29                     amount++;
    30                     sum=n[i];
    31                 }
    32                 else if(sum==mid)
    33                 {
    34                     amount++;
    35                     sum=0;
    36                 }
    37             }
    38             if(sum>0)
    39                 amount++;
    40             if(amount>N) left=mid+1;
    41             else
    42                 right=mid;
    43         }
    44         printf("%d
    ",left);
    45     }
    46     return 0;
    47 }
    View Code

    uva,11516

    方法 : binary search

    题意 : 寻找在题目提供的ap数量下 半径最小值

    做法 : Binary Serach 

    因为房子一定要被包到 所以可以假设房子刚好被ap覆盖到的情况下之最少距离
    因此以房子为準依直径向外扩张 最后题目所求的半径再用所得直径/2即得 
     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 int loc[100005];
     6 
     7 int main()
     8 {
     9     int tc;
    10     scanf("%d",&tc);
    11     while(tc--)
    12     {
    13         int s,h,i,lo,hi,mid;
    14         scanf("%d %d",&s,&h);
    15         for(i=0;i<h;i++)
    16             scanf("%d",&loc[i]);
    17         sort(loc,loc+h);
    18         lo=0;
    19         hi=2*(loc[h-1]-loc[0]+1);
    20         while(hi>lo)
    21         {
    22             mid=(lo+hi)/2;
    23             int start=loc[0];
    24             int needed=1;
    25             for(i=1;i<h;i++)
    26                 if(loc[i]>start+mid)
    27                 {
    28                     needed++;
    29                     start=loc[i];
    30                 }
    31             if(needed>s)
    32                 lo=mid+1;
    33             else
    34                 hi=mid;
    35         }
    36         printf("%.1f
    ",hi/2.00);
    37     }
    38     return 0;
    39 }
    View Code

    uva,10539

    题目先用线筛法打表,然后用前缀和法相减就可以了。

    注意题目意思:非质数且只能整除一个质数,即是一个质数的n次方。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxn 1000000
     5 using namespace std;
     6 typedef long long ll;
     7 int prime[maxn];
     8 int isprime[maxn+5];
     9 int ans;
    10 ll low,high;
    11 void Prime()
    12 {
    13     ans=0;
    14     memset(isprime,1,sizeof(isprime));
    15     for(int i=2;i<=maxn;i++)
    16     {
    17         if(isprime[i])  prime[ans++]=i;
    18         for(int j=0,tmp;j<ans && (tmp=i*prime[j])<=maxn;j++)
    19         {
    20             isprime[tmp]=0;
    21             if(!(i%prime[j])) break;
    22         }
    23         
    24     }
    25 }
    26 
    27 ll solve(ll n)
    28 {
    29     ll count=0;
    30     for(int i=0;i<ans;i++)
    31     {
    32         ll u=prime[i]*prime[i];
    33         if(u>n)
    34             break;
    35         while(u<=n)
    36         {
    37             u*=prime[i];
    38             count++;
    39         }
    40     }
    41     return count;
    42 }
    43 
    44 
    45 int main()
    46 {
    47     int N;
    48     Prime();
    49     scanf("%d",&N);
    50     while(N--)
    51     {
    52         scanf("%lld %lld",&low,&high);
    53         printf("%ld
    ",solve(high)-solve(low-1));
    54     }
    55     return 0;
    56 }
    View Code
    活在现实,做在梦里。
  • 相关阅读:
    javascript零散要点收集
    javascript闭包,arguments和prototype
    javascript面向对象规则汇总以及json
    递归转非递归的编程思想
    汇编要点汇总
    队列相关算法
    深度优先遍历算法
    C++面向对象要点
    堆排序
    快速排序算法
  • 原文地址:https://www.cnblogs.com/do-it-best/p/5364894.html
Copyright © 2011-2022 走看看