二分查找:双指针的特殊化版本
算法解释
二分查找常称为二分法或折半查找,每次查找时通过将待查找区间分为俩个部分并通过一个判断的法则来读取一部分的内容继续查找,将查找的复杂度大大降低。将一个长度为O(n)的数组,二分查找的时间复杂度时O(log(n))
注意事项
一定一定一定要注意区间的闭合关系,确定是左闭右开还是左开右闭还是别的法则,注意c++中的lower_bound和upper_bound函数。
具体的实例
leetcode 34
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
//二分查找
//upper_bound and lower_bound
//这里设计成左闭右开的区间吧,这样可以统一一下
int n = nums.size();
int lower = lower_bound(nums,target);
int upper = upper_bound(nums,target)-1;
if(lower==nums.size()||nums[lower]!=target)
{
return vector<int>{-1,-1};
}
return vector<int>{lower,upper};
}
int lower_bound(vector<int>&nums,int target)
{
int left = 0,right = nums.size(),mid;
while(left<right)
{
mid = (left+right)/2;
if(nums[mid]>=target)
{
right = mid;
}
else
{
left = mid+1;
}
}
return left;
}
int upper_bound(vector<int>&nums,int target)
{
int left = 0,right = nums.size(),mid;
while(left<right)
{
mid = (left+right)/2;
if(nums[mid]>target)
{
right = mid;
}
else
{
left = mid+1;
}
}
return left;
}
};