二分法是一种高效的查找算法,在一个由若干个数由小到大组成的一维数组中,设左边界为l,右边界为r,主要思想就是先找中间值mid=(l+r)/2,写一个check函数,便于判断mid是否满足该性质,比如check函数可定义成其他数分别与mid比较,如果比较结果为真,就进一步判断如何更新区间,如果更新方式是l=mid,那么mid就要变成(l+r+1)/2,也可写作l+r+1>>1.这里解释一下为什么有的时候加一,有的时候不加一,就是说当最后状态为l=r-1的时候,mid下取整得mid=l,此时更新方式为l=mid=l,好家伙,搞了半天又绕回原点了,更新后区间没有变,此时就会陷入死循环,所以就需要把mid变为(l+r+1)/2;
只要是我们要找的答案在一个区间内,我们就可以用二分。
值得注意的是,当数组长度为n,r=n时,while循环里的循环条件应该为l<r,此时while循环结束的条件为l=r,当r=n-1时,while循环里的循环条件为l<=r,此时while循环结束的条件为l>r.
这里附上leetcode上关于二分查找算法的两道例题,
这是leetcode第35题,搜索插入位置,
题解:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int l=0,r=nums.size(),mid;
while(l<r)
{
mid=(l+r)/2;
if(target==nums[mid]) return mid;
if(target<nums[mid]) r=mid;
else l=mid+1;
}
return l;
}
};
二分查找算法的时间复杂度为O(logn).
leetcode第704题:
题解:
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size()-1,mid;
while (l <=r)
{
mid = (l+r)/2;
if(target==nums[mid]) return mid;
if(target<nums[mid]) r=mid-1;
else l=mid+1;
}
return -1;
}
};
这里返回mid是一种特殊情况,此时把区间分成了[0,mid),{mid},(mid,r]三份,判断是否加一应该是先看区间的更新方式,如果更新方式是l=mid,也就是说把区间分成了[0,mid],[mid+1,r],就需要加一,如果是r=mid,则不需要加一.
本文到这里就结束了,有啥不清楚或者错误的地方希望各位大佬多多赐教o.