作用
- 可使查询得时间复杂度为O(log2n)
- 可将有序数组一分为二进行查询,增快查询速度
核心
- 目标值( Target) —— 你要查找的值
- 两个下标指针(left,right),决定了我们的搜索区间
- 中间下标值(mid)
- 根据和中间值的比较,决定left = mid+1 和 right = mid-1
- 目标值和mid做等值运算,相等返回,不相等继续运算,不和其他下标值做等值返回运算
- left+(right-left)/2可以防止数据溢出,如用left+right/2,那么 left+right> Interger.MAX_VALUE 时,此时会导致数据溢出
- while循环(left<=right),不符合则数组中没有,返回-1
流程
预处理 —— 如果数组中的元素未排序,则进行排序。
二分查找 —— 使用循环或递归在每次比较后将查找空间划分为两半。
后处理 —— 在剩余空间中确定可行的候选者。
实践
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
分析
首先这是有序得,所以不需要预处理排序,接下来我们确定好left和right下标值,就可以进行二分查找计算mid,与我们目标值进行比较,大于在mid下标的右边,不包含mid下标,小于在mid下标的左边,不包含mid下标,分别移动left下标指针到mid+1或移动right指针到mid-1,不断循环,直到mid值与我们目标值,相等,如果循环结束都没有相等,那么就return -1;
代码
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (right - left) / 2 + left ; // 防止数据溢出,也可写为((right - left) >> 1) + left
if (target == nums[mid]) {
return mid;
}
if (target > nums[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
}