搜索一个元素
最基础版本(搜索闭区间)
int binarySearch(int[] arr, int target) { int n = arr.length; int left = 0, right = n - 1; while(left <= right) { int mid = (left + right) / 2; if(arr[mid] == target) { return mid; }else if(arr[mid] < target) { left = mid + 1; } else if(arr[mid] > target) { right = mid - 1; } } return -1; }
搜索左边界(左闭右开区间),在该区间搜索一个值的左边界,如果不存在返回-1
// 在给定的单调区间里,找到target的左边界// 此处还有另一种理解方式,// 例如 arr = {1, 2, 3, 3, 4}// target = 3 的左边界的下标(left_bound)代表着 “小于target的数有left_bound个”// 考虑搜索区间的划分,对于区间[left, right),// 下一次搜索的区间为 [left, mid) 或 [mid+1, right)// 其中[left, mid) 包含了 [left, mid-1]// 对于target不存在arr中的情况的处理// 1.如果 target > arr[n-1],则 left == n// 2.如果 arr[i] < target < arr[j],其中 0 <= i < j < n// 有 arr[left] != leftint left_bound(int[] arr, int target) { int n = arr.length; int left = 0, right = n; // 注意:此处为左闭右开区间[left, right) while (left < right) { // 注意 int mid = (left + right) / 2; if (arr[mid] == target) { right = mid; // 缩小右边界,往左边搜索 } else if (arr[mid] < target) { left = mid + 1; } else if (arr[mid] > target) { right = mid; } } // 注意 if(left == n) return -1; return arr[left] == target ? left : -1; }
搜索右边界(左开右闭区间),在该区间搜索一个值的右边界,如果不存在返回-1
// 在给定的单调区间里,找到target的右边界// 此处还有另一种理解方式,// 例如 arr = {1, 2, 3, 3, 4}// target = 3 的右边界的下标(right_bound)代表着 “小于或等于target的数有left_bound个”// 此处和搜索左边界相同// 考虑搜索区间的划分,对于区间[left, right),// 下一次搜索的区间为 [left, mid) 或 [mid+1, right)// 其中[left, mid) 包含了 [left, mid-1]// 对于target不存在arr中的情况的处理// 1.如果 target < arr[n-1],则 left == 0// 为什么在搜索到target的情况下返回值是left-1?// 因为搜索的出口是left==right,而且我们对left的更新必定是mid+1,// 也就是说,当退出循环时,arr[left]必定不等于target,而arr[left-1]可能等于target// 这就需要我们去判断了int right_bound(int[] arr, int target) { int n = arr.length; int left = 0, right = n; // 注意 while(left < right) { int mid = (left + right) / 2; if(arr[mid] == target) { left = mid + 1; // 注意 }else if(arr[mid] < target) { left = mid + 1; }else if(arr[mid] > target) { right = mid; } } // 注意 if(left == 0) return -1; return arr[left-1] == target ? left -1 : -1; }
搜索边界
左边界

// 搜索左侧边界
int left_bound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
// 当找到 target 时,收缩右侧边界
right = mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
}
}
return left;
}
右边界

// 搜索右侧边界
int right_bound(int[] nums, int target) {
if (nums.length == 0) return -1;
int left = 0, right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
// 当找到 target 时,收缩左侧边界
left = mid + 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
}
}
return left - 1;
}