关于二分查找

65 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

二分查找也叫折半查找,它要求被查找表必须是顺序存储,而且表中元素要按照关键字序列排列。

二分查找核心是:将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则在前半部分表查找关键字,否则查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

在这种情况下:最快查到的时间是O(1),即它就刚好是重点值,最坏情况就是该元素不在表里面,需要一种查找玩表。

二分查找的实现:

public int erfen(int[] arr,int res){
int start=0;
int end=arr.length-1;
while(start<end){
int mid=(start+end)/2;
if(res==arr[mid]) return mid;
else if(res>arr[mid]){
start=mid+1;
}else{
end=mid-1;
}
return 1;
}

image.png

关于二分查找一个例题就是二维数组的查找。

题目描述:在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[ [1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15] ]

给定 target = 7,返回 true。

给定 target = 3,返回 false。

解法1:每一行使用一次二分查找

image.png

虽然这样做可行,但是时间复杂度太大了,所以舍去。

解法2,变成一维数组来二分查找。

因为使用二分查找需要有序,使用可以声明一共链表来存储二维数组值,然后对链表排序,拿到有序数组,然后进行二分查询。

如果原数组很大,那么我们空间复杂度会变大,使用还需要考虑其他方法。

解法3:假设就在原数组上进行线性搜索。

由于行列递增,可以得出: a.在一列中的某个数字,其上的数字都比它小 b.在一行中的某个数字,其右的数字都比它大 搜索流程: a.首先从数组左下角搜索. b.如果当前数字大于target,那么查找往上移一位,如果当前数字小于target,那么查找往右移一位。 c.查找到target,返回true; 如果越界,返回false;

这种情况我们就需要考虑边界条件了,如果数组位null输出false,如果目标值大于数组最后一位(最大位)以及目标值小于第一位(最小位),那么输出false。

可以从左下开始查找,也可以从右上查找,道理类似

int cols = array[0].length;
        // 左下
        int row = rows-1;
        int col = 0;
        while(row>=0 && col<cols){
            if(array[row][col] < target){
                col++;
            }else if(array[row][col] > target){
                row--;
            }else{
                return true;
            }
        }
        return false;