再也不怕面试遇到二分查找了
所谓二分查找就是题目要求在给定的数组或者序列中查找我们给定的元素,例如在数组a[5]={1,3,4,5,9}中查找元素5,一般我们能想到的最简单的方法就是暴力方法,直接依次遍历数组的每一个元素,然后和要查找的元素作比较,但是这种方法就是时间复杂度特别高,很多时候在力扣上是通不过的。那么就需要介绍二分查找,也是最常用的查找方法,二分就是将序列分为两部分,先将元素和中间的值作比较,如果大于中间的值,那么要查找的元素就在右半部分,就不需要再看左半部分了(二分查找的前提是一般序列是有序的),反之就不需要看右半部分,以上面的例子来说,我们先确定中间的位置的元素是4.小于要查找的元素5,那么前面的元素肯定也是小于5的。就不需要比较了,直接比较后面的两个元素就行,这样就可以得到我们想要查找的元素,同时效率也很高。通常的话我们是设置两根指针来标记元素的位置,如下所示:
如上图所示,我们开始的时候left指针指向第一个元素,right指针指向最后一个元素,那么中间的值就是4,用mid指针指向它,因为4小于5,说明要找的值在右边,所以此时right指针不动,left指针移动到mid的下一个位置,即5的位置,再在这个区间按照上面同样的方法进行查找;
若要找的元素是2,小于mid指针,那么left指针不动,right指针指向mid的前一个位置,这就是双指针法。那么接下来我们就来看看力扣上的几个二分查找的例题,一网打尽他们。
[704. 二分查找]
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left <= right) //这里是左闭右闭区间,可以取到最右边的值
{
int mid = left + (right-left) /2;
if(target < nums[mid])
{
right = mid-1;
}
else if(target > nums[mid])
{
left = mid +1;
}
else //mid== target
{
return mid;
}
}
return -1;//没有找到
}
};
方法二:(注意两种方法指针指向的位置的区别,不然老是会搞错)
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while(left < right) //这里是左闭右开区间,不能取到最右边的值
{
int mid = left + ((right-left)>>1) ;
if(target < nums[mid])
{
right = mid;
}
else if(target > nums[mid])
{
left = mid +1;
}
else //mid== target
{
return mid;
}
}
return -1;//没有找到
}
};
35、搜索插入的位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
//解题思路:二分查找
int i=0;
int j=nums.size()-1;
while(i<=j)
{
int mid = i+ (j-i)/2; //计算中间的值的位置
if(target ==nums[mid])
{
return mid;
}
else if(target < nums[mid])
{
j=mid-1;
}
else
{
i=mid+1;
}
}
return j+1; //没有找到,那么就要把元素插入到最后一个位置
}
};
[69. x 的平方根]
class Solution {
public:
int mySqrt(int x) {
//解题思路:x的平方根肯定是再0到x之间,那么就在这个区间进行二分查找即可
int i=0;
int j =x;
int ans =-1;
if(x==0)
{
return 0;
}
if(x==1)
{
return 1;
}
while(i<=j)
{
long long mid = i+(j-i)/2;
if(mid * mid == x)
{
return mid;
}
else if(mid * mid <x)
{
ans = mid; //这里是因为最终没找到的话也需要返回一个近似值。
i=mid+1;
}
else if(mid * mid >x)
{
j = mid -1;
}
}
return ans;
}
};
[367. 有效的完全平方数]
class Solution {
public:
bool isPerfectSquare(int num) {
//解题思路:所谓的完全平方数就是能够存在一个数的平方等于它,思路还是和平方根的方法类似,直接二分查找
int i =0;
int j = num;
if(num <2)
{
return true;
}
while(i<=j)
{
long long mid = i + (j-i)/2; //计算中间的值
if(mid * mid == num)
{
return true;
}
else if(mid * mid < num)
{
i=mid+1;
}
else if(mid * mid > num)
{
j = mid -1;
}
}
return false;
}
};
以上就是今天二分查找的几个例题,总体上都是比较简单,要注意的是在确定区间的时候需要确定到底是前闭后闭还是前开后闭得区间,稍不注意就要出错,可以参考第一题得两种方法进行区别。
看到一句书签上的话送给大家:
while IQ ==average and PS ==average:
if take heart:
skill = float("inf")