1、二分查找基本思想:
首先将要查找的元素 target 与数组中间元素mid比较;
1)如果 target 小于中间元素mid,只需要在数组前一半元素中继续查找;
2)如果 target 和中间元素mid相等,匹配成功,查找结束;
3)如果 target 大于中间元素mid,只需要在数组后一半元素中继续查找;
二分查找适用于——有序且不含重复元素的序列数组;
2、二分法的两种写法:
1)定义 target 是在一个在一个左闭右闭的区间里,也就是[left, right];while(left <= right), 更新left=mid+1 ,right = mid - 1;
int test(vector<int>& nums,int target) {
//找到目标值,返回数组下标,未找到返回-1
int left = 0;
int right = nums.size() - 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
{
return mid;
}
}
//未找到目标值 返回-1
return -1;
}
2)定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,while (left < right), 更新lleft=mid+1,right = mid;
int test(vector<int>& nums,int target) {
//找到目标值,返回数组下标,未找到返回-1
int left = 0;
int right = nums.size() - 1;
while (left<right)
{
int mid = left+((right-left)>>2);
if (nums[mid]<target) {
left = mid + 1;
}
else if (nums[mid] > target) {
right = mid;
}
else
{
return mid;
}
}
//未找到目标值 返回-1
return -1;
}
3、int型变量
int 是一种整型变量,占用 4 字节 32 比特时的取值范围是- 2147483648~2147483647,占用 2 字节 16 比特时的取值范围是- 32768~32767;
4、mid=(left+right)/2
二分查找时,求取中间值的操作步骤,写法mid = (left + right) / 2,这种写法存在问题。原因:left可能不断增大,如果到极限状态,也就是left达到了right-1的地步的时候刚好数组的长度又很大,那么就可能导致left + right的溢出出现负数;
#include<iostream>
using namespace std;
int main() {
int left = 1999999998;
int right = 1999999998;
int mid1 = (left + right) / 2;
int mid2 = left + (right - left) / 2;
cout << mid1 << endl; //-147483650
cout << mid2 << endl; //1999999998
system("pause");
return 0;
}
5、改进写法:mid=left+(right-left)/2或mid=left+((right-left)>>2)
——(right+left)相加的结果可能会导致整型溢出的情况,(right-left)使用减法不会超出最大的整型范畴;
——>>是右移运算符,右移一位相当于除2,右移n位相当于除以2的n次方;mid=(left+right)>>1等价于mid=(left+right)/2;
——left+(right-left)/2通分可知是等同于 (left + right) / 2;