【算法•日更•第一期】查找算法:简单实现二分
▎二分
☞『算法思想』
二分也就是二分查找,又叫折半查找。这种算法正如其名,每一次都要分一半。废话不多说,直接抛砖引玉:
Q:现在来思考一个问题:在一千以内我已经心中想好了一个数(不耍赖),你可以随意询问我一个数,我只会说大了、小了和猜对了,想必你一定玩过,那么请问怎样询问才能使用次数最少?
Answer:
其实有常识的人都知道,第一次说500;第二次说(第一次大了)250或(第一次小了)750;第三次125、375、625或875……以此类推。每一次都要砍一半询问,这样无疑不需要每个数都被查找一遍。如果你这样干过,那么可以说你已经会了二分的思想了。可能我没有说清楚,那么就再举个例子吧:(我心里想着666)
A:500?
B:小了
A:750?
B:大了
A:625?
B:小了
A:687?
B:大了
A:656?
B:小了
A:671?
B:大了
A:663?
B:小了
A:667?
B:大了
A:665?
B:小了
A:666?
B:猜对了
☞『算法复杂度分析』
由于每一次都会分掉一半,因此时间复杂度就是O(log n)。
形象一些说明就是最多查找n以2为底数的对数次。
对数:在数学中,对数是对求幂的逆运算,正如除法是乘法的倒数,反之亦然。(copy自百度)比如说n=1024,log 1024=10,因为210=1024。
☞『算法图解』
如果用图的形式来表示太out了,还是用自己做的flash吧,不喜勿喷。
☞『算法实现』
二分查找算法实现起来相对容易,就不加注释了,大概说一下流程:输入一串数字和被查找的数字 -> 排序(否则找出来的是错的)-> 二分查找 -> 输出是否有这个数字。
代码如下:
1 //二分查找 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 int number[10000],n,x; 6 int l,r,mid; 7 int main() 8 { 9 cin>>n; 10 for(int i=1;i<=n;i++) 11 cin>>number[i]; 12 sort(number+1,number+1+n); 13 cin>>x; 14 l=1;r=n; 15 while(l<=r) 16 { 17 mid=(l+r)/2; 18 if(x==number[mid]) 19 { 20 cout<<"success!"; 21 return 0; 22 } 23 if(x<number[mid]) r=mid-1; 24 if(x>number[mid]) l=mid+1; 25 } 26 cout<<"fail"; 27 return 0; 28 }
☞『算法思想』
典型的分治。
分治:分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)等等。(copy自百度)