base
最中间的二分 搜索区间为[l, r]
l = 0;
r = len - 1;
while (l <= r) {
mid = (l + r) / 2;
if (nums[mid] < target) {
l = mid + 1;
} else if (nums[mid] > target) {
r = mid - 1;
} else if (nums[mid] == target) {
return mid;
}
}
return -1;
缺点:有序数组 nums = [1,2,2,2,3],target = 2,此算法返回的索引是 2,不是左侧边界也不是右侧边界。
左侧边界的二分 搜索区间为[l, r)
l = 0;
r = len;
while (l < r) { // 注意 r 取不到
mid = (l + r) / 2;
if (nums[mid] < target) {
l = mid + 1;
} else if (nums[mid] > target) {
r = mid; // 分成两个区间 [l, mid-1) [mid, r)
} else if (nums[mid] == target) {
r = mid; // 注意这里,不返回,目的是找到最左边的索引
}
}
if (left == nums.length) return -1; //target大于所有数
if (nums[left] != target) return -1; //没找到
return l; // or r
最终得到的下标可以理解成,小于target的数有几个
右侧边界的二分 搜索区间为[l, r)
l = 0;
r = len;
while (l < r) {
mid = (l + r) / 2;
if (nums[mid] < target) {
l = mid + 1;
} else if (nums[mid] > target) {
r = mid; // 分成两个区间 [l, mid-1) [mid, r)
} else if (nums[mid] == target) {
l = mid + 1;; // 注意这里,不返回,目的是找到最右边的索引
}
}
if (left == 0) return -1; //target小于所有数
if (nums[left - 1] != target) return -1;
return l - 1; // 注意这里 因为 l = mid + 1, 所以mid = l - 1