算法复习笔记:二分查找

  在计算机科学中,折半搜索英语:half-interval search),也称二分查找算法binary search)、二分搜索法二分搜索二分探索,是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

实现:

int binarySearch(vector<int> &v,int x)
{
    int left = 0;
    int right = v.size() -1;
    while(left <= right)
    {
        int mid = left + ((right - left)>>1);
        if(v[mid] == x)
            return mid;
        else if(v[mid] < x)
            left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

注意问题

  1. 区间开闭。left和right表示算法当前处理的数组的最小下标和最大下标,上述采用闭区间[0,v.size()-1]。采用闭区间的判断条件为left<=right,如果用left<right在最后一个元素是会直接跳出[left,left]。
  2. 中间下标计算。平均值计算能出现除法性能较低,加法可能溢出采用mid = left + ((right - left)>>1)计算可避免。  
  3. 下标修改。采用+1-1修改的方式,修改之后新的区间肯定不会跟原区间一样,算法不会进入死循环。

 查找第一次出现

   在v的当前区间[left,right]中,数据为非递减序, 如果tar<=v[mid],则v[mid]右边的元素(不包括v[mid])全部都不符合要求 ,则right = mid;如果tar > v[mid], 则左边的元素包括v[mid]全部都小于tar,则left = mid +1; 此时循环条件在最后一个元素的时候,会出现死循环,需要改成left<right。

比如:

   当前状况:        tar == V[0], left == 0,right == 0

   计算:            mid = 0

   更新:          更新right = mid = 0;

int binarySearchFirst(vector<int> & v,int x)
{
    int left = 0;
    int right = v.size()-1;

    while(left < right)
    {
        int mid = left + ((right - left)>>1);
        if(x <= v[mid])
            right = mid;
        else
            left = mid + 1;
    }
    if(v[left] == x)
        return left;
    else
        return -1;

}


 查找最后一次出现

  在v的当前区间[left,right]中,数据为非递减序, 如果tar<v[mid],则v[mid]以及右边的元素全部都不符合要求 ,则right = mid - 1;如果tar >= v[mid], 则左边的元素v[mid]全部都小于tar,则left = mid ;  但是在最后两个元素的时候,循环会一直保持不变,所以采取的方法是   int mid = left + ((right - left + 1)>>1);

比如:

   当前状况:        tar == V[0], left == 0,right == 1

   计算:            mid = 0

   更新:          更新left = mid = 0;

int binarySearchLast(vector<int> &v,int x)
{
    int left = 0;
    int right = v.size()-1;

    while(left < right)
    {
        int mid = left + ((right - left + 1)>>1);
        if(x < v[mid])
            right = mid - 1;
        else
            left = mid ;
    }
    if(v[left] == x)
        return left;
    else
        return -1;
}

 

原文地址:https://www.cnblogs.com/fengyehe/p/5360099.html