1、经典二分查找模板
int search(vector<int>& nums, int target) {
int right = nums.size() - 1;
int left = 0;
while(left < right)
{
int mid = (left + right)/2;
if(nums[mid] > target)
{
right = mid-1;
}
else if(nums[mid] < target)
{
left = mid+1;
}
else
{
return mid;
}
}
if(right == left && nums[right] == target)
{
return right;
}
return -1;
}
通过不断更新左右左右边界,找到目标值。
细节问题:
1、每次更新都更新到 mid+1 或 mid-1位置。
2、循环结束条件为 left < right。
3、循环结束需要额外判断。
4、防止数组求取mid时值溢出可选用 left + (right - left)/2 ;
2、目标值小于等于右区间的模板
int left = 0;
int right = nums.size() - 1;
int resleft = 0;
int resright = 0;
while(left < right)
{
int mid = left + (right-left)/2;
if(nums[mid] >= target)
{
right = mid;
}
else
{
left = mid+1;
}
}
如图所示:绿色部分为目标值不存在的区间,红色部分为目标值可能存在的区间。
与经典二分算法不同的是:
当mid位置命中绿色部分时:left = mid + 1;
当mid位置命中红色位置时:right = mid;;
并且求取mid时遇到数组的size为偶数时,想要mid 靠左则使用 left = (right - left )/2;,想靠右使用 right = ( right - left + 1)/2 ;
此时要用left = (right - left )/2。
同样,结束循环时要判断。
3、目标值大于等于左区间的模板
while(left < right)
{
int mid = left + (right+1-left)/2;
if(nums[mid] <= target)
{
left = mid;
}
else
{
right = mid - 1;
}
}
如图所示:绿色部分为目标值不存在的区间,红色部分为目标值可能存在的区间。
与经典二分算法不同的是:
当mid位置命中绿色部分时:right = mid - 1;
当mid位置命中红色位置时:left = mid;;
并且求取mid时遇到数组的size为偶数时,想要mid 靠左则使用 left = (right - left )/2;,想靠右使用 right = ( right - left + 1)/2 ;
此时要用( right - left + 1)/2
同样,结束循环时要判断。