数据结构与算法是面试中必问的
---同行者联盟
二分查找《折半查找》
1、什么是二分查找
二分查找是一种基于比较目标值和中间元素的查找算法。
比如你在一个有序的书架上寻找一本书,书架上的书按照书名字母顺序排列。你知道你要找的书的书名,但你不知道它在书架上具体的位置。如果你从书架的一端开始,一本一本地查找直到找到目标书,这样做的效率非常低 。
采用二分查找的方法。首先,找到书架的中心位置,并将它与目标书的书名进行比较。如果目标书名在中心书的左侧,那么你可以将搜索范围缩小到书架的左半部分,否则你可以将搜索范围缩小到书架的右半部分。然后,你可以在新的搜索范围内重复这个过程,直到你找到目标书为止。
这种方法比一本一本地查找的方法要快得多,因为每次搜索都将搜索范围缩小了一半。这就是二分查找的基本思想。
2、二分查找的原理
二分查找的原理很简单,它利用了有序数组的性质。具体来说,我们首先比较目标值和中间元素的大小关系,如果目标值小于中间元素,则在左半部分继续查找;如果目标值大于中间元素,则在右半部分继续查找;如果目标值等于中间元素,则返回中间元素的索引位置。
通过不断缩小查找范围,最终我们可以找到目标值。每次查找的时间复杂度为O(logn),比线性查找的时间复杂度O(n)要快得多。
举个例子,我们在喝酒的时候经常会玩一个叫猜数游戏,张三在纸条上写一个从1到100的数,李四猜,李四会有几次猜错的机会,如果在机会用完之前猜中了,张三喝酒,机会用完之后仍没有猜中,则李四喝酒。 当李四猜完某个数后,张三会根据猜的数回答大还是小(猜的数相对于目标数而言)
比如张三写了个76,
第一回合,假如李四猜50,小,说明目标数在51到100之间;
第二回合 李四会猜75,小,说明目标数在76到100之间;
第三回合 李四猜88,大,说明目标数在76到87之间;
第四回合 李四猜81,大,说明目标数在76到81之间......
其实这个游戏本质就是二分查找,只有这样才可能更快的找到目标数据
3、二分查找的图解
给定一个有序数组1到9,查找目标数6是否在数组中,在的话其对应的索引是多少
left=0,right=8,先找到中间元素的索引,即(0+8)/2=4,比较目标数6和arr[4]的大小,arr[4]值为5,5小于6,此时left=mid+1,right不变;
继续计算索引mid=(left+right)/2对应的只为7,6小于7,所以此时left不变,right编程mid-1
此时的left和right都是5,所以mid=(left+right)/2也为5,arr[5]==6,所以找到目标数,目标数所在索引为5
4、二分查找的实现
给定一个有序数组[1,3,5,7,10,12,17,23,78],查询目标数据在数组中的位置,不在则返回-1,否则返回索引值
代码实现如下:
public int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
// 当数组里面没有值了,就得退出了
while (left <= right) {
// 先得到中间索引
int mid = (left + right) / 2;
// 检测中间索引元素是否为目标元素
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
// 没有找到目标元素,返回-1
return -1;
}
5、二分查找的优点
1、时间复杂度低:二分查找的时间复杂度为O(logn),在大规模数据处理的场景下,二分查找可以显著减少搜索时间。
2、适用范围广:二分查找可以用于查找有序数组或有序列表中的元素。
3、实现简单:二分查找的实现相对简单,只需要几行代码即可完成。