1、简要概述
因为按元素排列顺序在数组中查找元素效率太低了,每次都要从头到尾去遍历元素。对此聪明的科学家研究出了二分查找算法,一种更高效的查询方法。
使用前提:数组中无重复的元素并且数组是有序的。
算法逻辑:定义两个首尾指针,及其中点元素,每次将中点值与目标值进行比对,比目标值小右指针收缩,比目标值大左指针收缩,不断重复直到找到目标值或者首尾指针重叠越界。
其逻辑类似与排除法,将不必要的元素排除在外,只搜寻目标区间内的元素,省去了很多不必要的检测,从而极大的提高了查找效率
2、例题实战
力扣:704题 . - 力扣(LeetCode)
实现代码:
class Solution {
public int search(int[] nums, int target) {
//定义首尾指针
int l = 0;
int r = nums.length - 1;
//确定查找区间
while(l <= r){
//中点元素
int mid = l + r >> 1;
//缩小寻找范围
if(nums[mid] < target) l = mid + 1;
else if(target < nums[mid]) r = mid - 1;
else return mid;
}
return -1;
}
}
代码逻辑:
在区间 [l,r]中查找目标元素
目标值比中间值小,缩小区间为 [l,mid - 1] (因为mid处的值肯定不是目标值,因此下一次搜索的地方在mid - 1后)
目标值比中间值大,缩小区间为 [mid + 1, r]
例题2:力扣35题 . - 力扣(LeetCode)
class Solution {
// public int searchInsert(int[] nums, int target) {
// int l = 0;
// int r = nums.length;
// while(l < r){
// int mid = l + r >> 1;
// if(nums[mid] == target) return mid;
// else if(nums[mid] < target) l = mid + 1;
// else r = mid;
// }
// return l;
// }
public int searchInsert(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while(l <= r){
int mid = l + r >> 1;
if(nums[mid] == target) return mid;
else if(nums[mid] < target) l = mid + 1;
else r = mid - 1;
}
return l;
}
}
注释部分逻辑:
搜索区间[l,r), 注意此次搜索区间不包括右端点,所有初始赋值时r = nums.length
当目标值比中点值小时,缩小右区间,r = mid
为什么这次不是,r = mid - 1 呢?
原因,要搜索的区间是[l , r ) 右边界不包括r处,当右边界需要缩小时,此时mid处已经被判断过了,不会是目标点
而mid - 1我们无法确定,所有我们让 r = mid
如果让 r = mid - 1,区间就会变成[l, r]
3、自我挑战
力扣1044题:. - 力扣(LeetCode)