二分查找:
二分查找,是查找一个数的好方法。
其优点在于:因为是折半查找,时间复杂度:O(logn)
而缺点在于:查找的序列必须得是有序序列。
对于二分查找,我们一般是查找一个数列的里的一个数,代码如下:
var
n,i,l,r,mid,x:Longint;
a:Array[1..100] of longint;
begin
readln(n);
for i:=1 to n do
read(a[i]);
readln(x);
l:=1;
r:=n;
while l<=r do
begin
mid:=(l+r) div 2;
if a[mid]=x then
begin
writeln(mid);
halt;
end;
if x<a[mid] then
r:=mid-1
else
l:=mid+1;
end;
end.
这里的mid是指第几个数,这是最最普通的二分查找。在这里先复习一下,注意while条件的地方是l<=r。
但如果把问法改一下,改成在一个有序序列里有多少个数小于等于x?这时候能用二分查找吗?答案是:当然能!
但是二分查找是查找一个数,而这里只是说小于等于x,很有可能x不在这个有序序列里,这时候怎么办呢?
我们知道在二分里,mid是指查找的数的位置,l最后表示的是最后一个二分范围的最低值,r与l相反。而如果x有可能不在这个序列的话,我们是否可以判断出l的位置就是小于等于x的位置。
经过在草稿纸上的分析和推断可以得出,如果要判断出l的话,l的初值应该为0,而r的初值则要为n+1.当a[mid]<=x的时候,l=mid。
这里有几个地方需要注意:为什么是<=,而不是<?因为题目说了是<=x的也算,所以这里一定得加等于号.
然后为什么l是=mid,而不是=mid+1呢?因为如果是mid+1的话当a[mid]=x的时候就不正确了,所以如果是Mid的话,也是不会错的。
a[mid]>x的时候r=mid,最后l就是小于等于x的个数了。
贴贴代码吧:
l:=0; r:=n+1;
while l<r do
begin
<span style="white-space:pre"> </span>mid:=(l+r) div 2;
if a[mid]<=x then l:=mid else r:=mid;
end;
inc(tot,l);