今天给大家介绍一下简单的二分法(刷题第一步!)
二分查找有个很明显的特点就是有序,这个特点同学如果在题中看到就要格外注意
一定要看完,基本的三种解法,后面还有真题链接哦!!
第一种
就是最最基础的左闭右闭的区间
class Solution {
public:
int search(vector<int>& nums, int target) {//vector和python里的list有异曲同工之处
int left=0;
int right=nums.size()-1;
//这里也可以用right=sizeof(nums)/sizeof(nums[0]);
while(left<=right)//注意!!!
{
int mid=(right-left)/2+left;
if(nums[mid]>target)
{
right=mid-1;//注意!!!
}
else if(nums[mid]<target)
left=mid+1;//注意!!!
else
return mid;
}
return -1;
}
};
为什么说它基础,应为你不用考虑right是否合法啊,这样要注意的有如下两点
1.循环判断时:while(left<=right),这里就有同学问了,why "<=" ? 哈哈哈,因为是此时是[left, right],所以 "left==right"这时候是有意义的。
2.当判断完满足条件 nums[mid] < target 后,要缩小区间范围了,right此时可以等于 mid-1,因为当满足nums[mid] < target这个条件时,nums[mid] != target这个已经确定,所以right=mid-1;同理left也是,只不过 left=mid+1,大同小异。
如果大家还有疑惑,我就偷个图让大家看看,哈哈哈
第二种
就是和第一种有些许不同的左闭右开区间,可别小看这一个点,把上面两个全改变了!!
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();//注意!!!
while(left<right)//注意!!!
{
int mid=(right-left)/2+left;
if(nums[mid]>target)
right=mid; //注意!!!
else if(nums[mid]<target)
left=mid+1;
else
return mid;
}
return -1;
}
};
这个和上面截然不同的两点
1.循环判断条件:while (left < right),哈哈哈,这里就有同学恍然大悟,应为现在"left==right",根本就不合法。
2.判断条件,if (nums[mid] > target) 时,right = mid,因为是开区间,这里如果 right=mid+1,就相当于漏掉了nums[mid+1],原因也是区间右边是开区间,所以现在 right=mid时已经表示了“ target ! = num[mid]”,这里可不能出错哦!
3.多了个对小白来说,还是要说说,这时 right由于是开区间,所以最开始时,right=nums.size()
如果有小伙伴还不理解,呢我就只能勉为其难,再偷个图,让大家看看了
介绍完以上两种,呢就再说一个最简单的吧!
第三种
暴力解法:基于二分查找的有序(可能最快,真的!!!)
由于已经有序,这时从头遍历如果遇到" target==nums[i] ",就" return i ",不就万事大吉了,时间复杂度也是O(n),空间也是O(1) ,如果碰到简单的二分查找完全就不需要搬框架,直接暴力就行
class Solution {
public:
int search(vector<int>& nums, int target) {
int num=nums.size();
for(int i=0;i<num;i++)
{
if(nums[i]==target)
return i;
}
return -1;
}
};
看完模板就试试上手做点题吧!
大家可以关注我,这两天,会把这四个题尽量用这三种方法更新至博客哦!!
已更新,写完了——>点这里链接