二分查找相关题解
1. 二分查找
算法思路:
a. 定义 left,right 指针,分别指向数组的左右区间。
b. 找到待查找区间的中间点 mid,找到后分三种情况讨论: i. arr[mid]==target 说明正好找到,返回 mid 的值; ii. arr[mid]>target 说明 [mid,right] 这段区间都是大于 target 的,因此舍去右边区间,在左边 [left,mid-1] 的区间继续查找,即让 right=mid-1,然后重复 b 过程; iii. arr[mid]<target 说明 [left,mid] 这段区间的值都是小于 target 的,因此舍去左边区间,在右边区间 [mid+1,right] 区间继续查找,即让 left=mid+1,然后重复 b 过程;
c. 当 left 与 right 错开时,说明整个区间都没有这个数,返回 -1。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
while(left<=right){
//int mid=(left+right)/2;可能会溢出
int mid=left+(right-left)/2;
if(nums[mid]<target) left=mid+1;
else if(nums[mid]>target) right=mid-1;
else return mid;
}
return -1;
}
};
2. 在排序数组中查找元素的第一个和最后一个位置
算法思路:
用的还是二分思想,就是根据数据的性质,在某种判断条件下将区间一分为二,然后舍去其中一个区间,然后在另一个区间内查找。
以下用 x 表示该元素,resLeft 表示左边界,resRight 表示右边界。
寻找左边界思路:
● 寻找左边界: ● 可以注意到一左边界划分的的两个区间的特点: ▢ 左边区间 [left,resLeft-1] 都是小于 x 的; ▢ 右边区间(包括左边界)[resLeft,right] 都是大于等于 x 的; ● 因此,关于 mid 的落点,我们可以分为以下两种情况: ● 当我们的 mid 落在 [left,resLeft-1] 区间时,即 arr[mid]<target。说明 [left,mid] 都是可以舍去的,此时更新 left 到 mid+1 的位置,继续在 [mid+1,right] 上寻找左边界; ● 当 mid 落在 [resLeft,right] 的区间的时候,也就是 arr[mid]>=target。说明 [mid+1,right](因为 mid 可能是最终结果,不能舍去)是可以舍去的,此时更新 right 到 mid 的位置,继续在 [left,mid] 上寻找左边界; ● 由此,就可以通过二分,来快速寻找左边界;

