简介
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
查找过程
在一组有序的顺序表中查找某个元素,比如是升序的数组,先比较该数组中间的值和元素大小关系,若数组中间的值大于元素,则下一次查找仅需要查找数组的前半段,若数组中间的值小于元素,则下一次查找仅需要查找数组的后半段,若数组中间的值等于元素就找到了,这些操作可以一直循环进行。
算法要求
要进行二分查找对数据结构是有要求的
1.必须采用顺序存储结构。
2.必须按关键字大小有序排列。
比较次数
计算公式:
当顺序表有n个关键字时:
查找失败时,至少比较a次关键字;查找成功时,最多比较关键字次数是b。
注意:a,b,n均为正整数。
算法复杂度
二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.
时间复杂度无非就是while循环的次数!
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,....n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O(h)=O(log2n)
SHOW THE CODE
牛客网上刷到一个在二维数组中查找元素是否存在的题目,就可以用到二分查找法。
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
public class Solution {
public boolean Find(int target, int [][] array) {
//for循环,以数组的行数为限
for(int i = 0;i<array.length;i++){
//最低位以0开始
int low = 0;
//最高位以数组长度为限
int high = array[i].length -1;
//while循环,当最低位小于等于最高位
while(low<=high){
//计算中间元素的位置
int mid = (low+high)/2;
//若当前行中间元素小于目标元素,说明正确的值可能在当前行的右半段
if(array[i][mid] < target){
//将最低位赋值为中间位+1
low = mid+1;
}
//若当前行中间元素大于目标元素,说明正确的值可能在当前行的左半段
else if(array[i][mid] > target){
//将最低位赋值为中间位+1
high = high - 1;
}else{
//否则就是找到目标元素,返回true
return true;
}
}
}
//for循环找不到目标元素则返回false
return false;
}
}
二分查找法充分利用了元素间的次序关系,采用分治策略来进行运算。而这道题明确了顺序排序的线性表的特点,这样我们就可以使用二分查找法作为算法来解决问题了。