目录
-
二分查找——适用范围
-
二分查找——递归写法
-
二分查找——非递归写法
1.适用范围
有序序列(默认为升序)中查找key或者查找符合条件的target(第一个符合条件的target或者是最后一个符合条件的target)。
2.递归写法
int target = 666;
int binarySearch(vector<int> nums, int low, int high) {
//递归出口,
if (low > high) {
return low;
}
//mid = low + (high - low) / 2相比于mid = (low + high) / 2的好处在于可以防止溢出
//前者中计算的中间变量及结果都不会超出high,后者计算的中间变量low+high有可能超出high
int mid = low + (high - low) / 2;
if (nums[mid] >= target)
return binarySearch(low, mid - 1);
else
return binarySearch(mid + 1, high);
}
查找结果可以分为(放在非递归部分解释):
①nums中存在target
- 第一次出现target的下标
- 最后一次出现target的下标
②nums中不存在target
- 第一个大于target的下标或者最大下标+1
- 最后一个小于target的下标或者最小下标-1
3.非递归写法
非递归写法的时间复杂度和空间复杂度比递归写法均更低,且更容易理解。
写法一:
int binarySearch(vector<int> nums, int target) {
int low = 0,high = nums.size()-1;
while(low<=high){
int mid = low + (high-low)/2;
if(target>nums[mid]){
low=mid+1;
}
else{
high=mid-1;
}
}
//如果nums中有多个target,结果返回第一个出现的target下标
//如果nums中没有target,当nums={1,2,3},target=4时,结果返回最大下标+1(溢出),其他情况返回第一个大于target的下标
return low;
}
Summary:target存在则返回首次出现的下标,不存在则返回大于target的最小值下标(溢出可以通过判断target是否超过最小值or最大值避免)
写法二:
int binarySearch(vector<int> nums, int target) {
int low = 0,high = nums.size()-1;
while(low<=high){
int mid = low + (high-low)/2;
if(target>=nums[mid]){
low=mid+1;
}
else{
high=mid-1;
}
}
//如果nums中有多个target,结果返回最后一个出现的target下标
//如果nums中没有target,当nums={5,6,7},target=4时,结果返回最小下标-1(溢出),其他情况返回最后一个小于target的下标
return high;
}
Summary:target存在则返回最后一次出现的下标,不存在则返回小于target的最大值下标(溢出可以通过判断target是否超过最小值or最大值避免)