最普通的二分查找(无重复元素的有序数列)
int binary_search(int[] nums, int target) {
int left = 0, 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) {
return mid;
}
}
return -1;
}
int mid = left + (right - left) / 2;
这种写法是防止left+right
出现越界的情况- 我们每次查找的范围 [left,right],因此while的退出条件是left>right
- 上面这个原因也决定了,每次搜索范围的变化都是
left = mid + 1;
和right = mid - 1;
因为num[mid]这个值已经检查过了不是想要的元素
找左边界的二分查找(有重复元素的有序数列)
int left_bound(int[] nums, int target) {
int left = 0, 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) {
right = mid - 1;
}
}
if (left >= nums.length || nums[left] != target)
return -1;
return left;
}
- 这种情况与之前不同的是,当我们找到target的时候并不急于返回,而是收缩上边界继续逼近
- 由于 while 的退出条件是 left == right + 1,所以当 target 比 nums 中所有元素都大时,会存在以下情况使得索引越界。因此要进行单独检查

找右边界的二分查找(有重复元素的有序数列)
int right_bound(int[] nums, int target) {
int left = 0, 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;
}
- 找右边界就是一样的道理了,与左边界唯一的不同点在于,找到target的时候是收缩left的范围
- 同样当 target 比所有元素都小时,right 会被减到 -1,所以需要在最后防止越界
