一、二分查找
1.例题
二分查找(简单)

2.实现
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
return -1;
}
}
3.解析
- 根据题目提示信息,本题不需要考虑数组为空。
- right的值取 nums.length - 1,表示搜索区间为[left, right],当“left == right + 1”(相当于[right + 1, left]),此时区间没有值,不需要再进行比较,因此跳出循环的条件应该为left <= right。
- left + (right - left) / 2 相当于 (right + left) / 2,但是前者能够有效防止
left
和right
的值太大且直接相加导致溢出。 - 当中间值nums[mid] 等于目标值时,返回数组下标(本题元素不重复)。
- 当中间值小于目标值时,则去右半边的数组中继续搜索,左指针left = mid + 1,同理,大于目标值时,right = mid - 1(本题数组是升序)。
二、寻找左右边界的二分查找
1.例题
在排序数组中查找元素的第一个和最后一个位置(中等)


2.实现
class Solution {
public int[] searchRange(int[] nums, int target) {
return new int[] {left_bound(nums, target), right_bound(nums, target)};
}
private int left_bound(int[] nums, int target) {
if (nums.length == 0)
return -1;
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
right = mid - 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
if (left >= nums.length || nums[left] != target)
return -1;
return left;
}
private int right_bound(int[] nums, int target) {
if (nums.length == 0)
return -1;
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
if (right < 0 || nums[right] != target)
return -1;
return right;
}
}
3.解析
- 当nums[mid] == target时,不能直接返回,而是缩小边界继续搜索。
- 最后要判断left 和 right的值,防止数组越界异常。
- 返回值为什么是left 或者 right?
这里以左边界举例,right变化的条件是nums[mid] >= target。

如图所示,搜索过程中右边界收缩,当right
停止变化时,即nums[right1] == target,且right1是目标值的左边界下标
,此时left
会往右走,一直到left == right2
,最终left = right2 + 1 = right1
,所以返回值是left
。
当nums[right1] > target,且nums[mid] < target
时,left 会往右移动,如果数组中不存在target
时,left 最终也会等于新的right
。
(右边界思路同左边界一样)