704.二分查找
使用二分查找的前提:
1.数组得是有序的(有些题可以后期自己排序 C++ sort排序得掌握)
2.数组中不能有重复元素
两个思路:1.左闭右开 2.左闭右闭
核心思路是利用left right两个指针 收敛的性质 判断mid是否和目标数重合
优化写法:mid = (right-left)/2+left; 防止right数值过大溢出;
左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
//左闭右开
int l = 0;
int r = nums.size();
while(l<r){
int mid = (r-l)/2 + l;
if(nums[mid]==target){
return mid;
}else if(nums[mid]<target){
l = mid+1;
}else{
r = mid;
}
}
return -1;
}
};
左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
//左闭右闭
int l = 0;
int r = nums.size();
while(l<=r){
int mid = (r-l)/2 + l;
if(nums[mid]==target){
return mid;
}else if(nums[mid]<target){
l = mid+1;
}else{
r = mid-1;
}
}
return -1;
}
};
- 时间复杂度:O(log n)
- 空间复杂度:O(1)
为什么两个写法的while判断语句,一个是left<right一个是left<=right?
在于左闭右开写法,右边的指的数不会真正被取到,当目前中间数大于目标数时,让right=mid。如果让right=mid-1则会出现mid-1这个数被跳过的问题。
所以这道题的核心思想,我认为不是背模板,而是搞懂这个区间的思路。不管是左闭右开,还是左闭右闭。我们要明白最后二分法是和区间收敛过程中的mid相比的。如果左右都能被取到的话,则在二分法的过程中就可以让left=mid+1 和 right=mid -1了。