二分法:思想是非常简单的,但是细节的地方还是比较困难,很多不同的情况下使用不一样的实现。
left = 0 left的值都是初始化为:0
代码模块如下:
int binarySearch(vector<int>nums, int target) {
int left = 0, right = ...;
while(...) {
int mid = (left + right ) / 2;
if(nums[mid] == target) {
...;
} else if(nums[mid] < target) {
left = ...;
} else if(nums[mid] > target) {
right = ...;
}
}
return ...;
}
第一个:最基本的二分查找算法,就是当其中的元素不重复出现的时候寻找对应的元素的位置的方法代码实现。
因为初始化 right = nums.size() - 1;
则自然决定搜索空间为: [left, right] 即前闭后闭
所以决定了 while(left <= right)
同时也决定了 left = mid + 1 和 right = mid - 1
这样的情况只是需要找到一个target的索引即可
所以当 nums[mid] = target 时候可以立即返回!
第二个,寻找左侧边界的二分查找:
因为这个时候初始化:right = nums.size();
所以决定了搜索区间为:[left, right)
同时其中的while(left < right)
left = mid + 1 和 right = mid;
这个时候是可以找到target的最左侧的索引的。
所以当其中的nums[mid] = target的时候不可以直接返回。
需要继续减小右侧的边界来锁定左侧的边界!
第三个:寻找右侧边界的二分查找算法:
因为我们初始化 right = nums.length
所以决定了我们的「搜索区间」是 [left, right)
所以决定了 while (left < right)
同时也决定了 left = mid+1 和 right = mid
因为我们需找到 target 的最右侧索引
所以当 nums[mid] == target 时不要立即返回
而要收紧左侧边界以锁定右侧边界
又因为收紧左侧边界时必须 left = mid + 1
所以最后无论返回 left 还是 right,必须减一
综上,三种不同的情况分别区分理解来结合使用!