二分查找模版

模版

第⼀个,最基本的⼆分查找算法:

因为我们初始化 right = nums.length - 1

所以决定了我们的「搜索区间」是 [left, right]

所以决定了 while (left <= right)

同时也决定了 left = mid+1 和 right = mid-1

因为我们只需找到⼀个 target 的索引即可

所以当 nums[mid] == target 时可以⽴即返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

第⼆个,寻找左侧边界的⼆分查找:

因为我们初始化 right = nums.length

所以决定了我们的「搜索区间」是 [left, right)

所以决定了 while (left < right)

同时也决定了 left = mid + 1 和 right = mid

因为我们需找到 target 的最左侧索引

所以当 nums[mid] == target 时不要⽴即返回

⽽要收紧右侧边界以锁定左侧边界

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
}
// 最后要检查 left 越界的情况
if (left >= nums.length || nums[left] != target) return -1;
return left;
}

第三个,寻找右侧边界的⼆分查找:

因为我们初始化 right = nums.length

所以决定了我们的「搜索区间」是 [left, right)

所以决定了 while (left < right)

同时也决定了 left = mid + 1 和 right = mid

因为我们需找到 target 的最右侧索引

所以当 nums[mid] == target 时不要⽴即返回

⽽要收紧左侧边界以锁定右侧边界

⼜因为收紧左侧边界时必须 left = mid + 1

所以最后⽆论返回 left 还是 right,必须减⼀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}
}
// 最后要检查 right 越界的情况
if (right < 0 || nums[right] != target) return -1;
return right;
}

注意

1、分析⼆分查找代码时,不要出现 else,全部展开成 else if ⽅便理解。

2、注意「搜索区间」和 while 的终⽌条件,如果存在漏掉的元素,记得在

最后检查。

3、如需定义左闭右开的「搜索区间」搜索左右边界,只要在 nums[mid] ==

target 时做修改即可,搜索右侧时需要减⼀。

4、如果将「搜索区间」全都统⼀成两端都闭,好记,只要稍改 nums[mid]

== target 条件处的代码和返回的逻辑即可,