在[3 5 7 9]数组中寻找9:
nums[mid] > target 的时候,target在左半边,j = mid - 1;
nums[mid] < target 的时候,target在右半边,i = mid + 1;
nums[mid] = target 的时候,表明找到了target,直接return。
疑问:下面为什么需要 left <= right?
其他算法遇到 “left <= right” 不确定到底要不要 “=”,就问自己一句,剩余一个元素是否需要进行循环!
//二分查找
int BinarySearch(vector &nums, int target){
int left = 0, right = nums.size() - 1;
while(left <= right){
int mid = (left + right) >> 1;// 或者 left + (right - left) /2;
if(nums[mid] == target)
return mid;
if(nums[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
return -1;
}
寻找数组中大于等于给定元素的二分查找法,类似于 lower_bound 函数:
1.arr[mid] >= x 的时候,mid对应的元素可能是最终结果,更新result = mid,r = mid - 1(因为mid已经被存放到结果中,无需考虑arr[mid]),如果没有被修改,那么最终结果就是arr[mid],否则就是修改后的值(被修改说明mid左侧还有大于等于x的值)。
2.arr[mid] < x 的时候,x 在右半边,l = mid + 1;
#include
using namespace std;
int binarySearch(int arr[], int n, int x) {
int l = 0, r = n - 1;
int result = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (arr[mid] >= x) {
result = mid;
r = mid - 1;
}
else
l = mid + 1;
}
return result;
}
int main() {
int arr[] = { 2, 3, 4, 4, 4, 10, 10, 40 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 10;
int result = binarySearch(arr, n, x);
if (result == -1)
cout << "Element not present in array";
else
cout << "First element greater than or equal to " << x << " is " << arr[result];
return 0;
}
寻找数组中大于给定元素的二分查找法,类似于 upper_bound 函数:
1.arr[mid] > x 的时候,mid对应的元素可能是最终结果,更新result = mid,r = mid - 1(因为mid已经被存放到结果中,无需考虑arr[mid]),如果没有被修改,那么最终结果就是arr[mid],否则就是修改后的值(被修改说明mid左侧还有大于等于x的值)。
2.arr[mid] <= x 的时候,x 在右半边,l = mid + 1;
注意:对于[0, 2, 2]中寻找第一个大于2的,返回值是-1,也就是找不到。
#include
using namespace std;
int binarySearch(int arr[], int n, int x) {
int l = 0, r = n - 1;
int result = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (arr[mid] > x) {
result = mid;
r = mid - 1;
}
else
l = mid + 1;
}
return result;
}
int main() {
int arr[] = { 2, 3, 4, 4, 4, 10, 40 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 4;
int result = binarySearch(arr, n, x);
if (result == -1)
cout << "Element not present in array";
else
cout << "First element greater than " << x << " is " << arr[result];
return 0;
}
对于数组[5 7 7 8 8 8 9 10],寻找8的左右边界(最小和最大下标)。
特别注意,当数组中不存在该元素时需要及时返回!
1、左边界寻找:
nums[mid] > target 的时候,target在左半边,j = mid - 1;
nums[mid] < target 的时候,target在右半边,i = mid + 1;
nums[mid] = target 的时候,左边界在[i, mid]区间内,j = mid。
2、右边界寻找:
nums[mid] > target 的时候,target在左半边,j = mid - 1;
nums[mid] < target 的时候,target在右半边,i = mid + 1;
nums[mid] = target 的时候,右边界在[mid, j]区间内,i =mid。
有边界有两种特殊情况。
class Solution {
public:
int search(vector& nums, int target) {
if(nums.size() == 0)return 0;
return binary_search(nums, target);
}
int binary_search(vector& nums, int target)
{
// 先找左边界
int i = 0, j = nums.size() - 1;
int m = 0;
while(i < j)
{
m = i + (j-i)/2;
if(nums[m] > target)j = m - 1;
else if(nums[m] < target)i = m + 1;
else if (nums[m] == target)j = m;
// cout<< "ertg"< target)j = m - 1;
else if(nums[m] < target)i = m + 1;
else if (nums[m] == target)i = m;
// 处理两种特殊情况
if(nums[i] == target && j - i == 1)
{
if(nums[j] != target)// 第一种
{
j = i;// j == i == m
break;
}
else i++;// 第二种
}
// cout<< "111"<