二分查找合集
最简单的二分查找
略
找target的左边界,如果没有则返回-1
重点在于nums[mid] == target的时候,收缩右边界
int leftBound(vector<int> &nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if(nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if(left == nums.size() || nums[left] != target)
return -1;
else
return left;
}
找target的右边界,如果没有则返回-1
int rightBound(vector<int> &nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if(nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] < target) {
left = mid + 1;
} else {
left = mid + 1;
}
}
// 结束的时候right == left - 1, right就是left左边的那个
// 因为每次收紧区间前,left = mid + 1,所以在循环结束后left不可能是target,只有right才有可能是target
// 画一画就知道了,left/mid/right先会在同一个位置,然后left右移right不变
if(right < 0 || nums[right] != target)
return -1;
else
return right;
}
利用找左边界的方法,实现lower_bound的功能(找到第一个大于等于target的位置)
重点在于nums[mid] == target的时候,收缩右边界
int leftBound(vector<int> &nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if(nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
// 这里非常简洁,因为left会根据数据的情况保持为0或者变为nums.size()
return left;
}