代码题(57)— 二分查找总结

1、第一类: 需查找和目标值完全相等的数

举例:704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(nums.empty())
            return -1;
        int low = 0;
        int high = nums.size()-1; //此处是减1,下面就是 <= 
        while(low <= high)
        {
            int mid = (low+high)/2;
            if(nums[mid] == target)
                return mid;
            else if(nums[mid] > target)
                high = mid-1;
            else
                low = mid+1;
        }
        return -1;
    }
};

2、第二类: 查找第一个不小于目标值的数,可变形为查找最后一个小于目标值的数

  因为我们要查找的目标值不一定会在数组中出现,也有可能是跟目标值相等的数在数组中并不唯一,而是有多个,那么这种情况下nums[mid] == target这条判断语句就没有必要存在。比如在数组[2, 4, 5, 6, 9]中查找数字3,就会返回数字4的位置;在数组[0, 1, 1, 1, 1]中查找数字1,就会返回第一个数字1的位置。我们可以使用如下代码:

int find(vector<int> &nums, int tar)
{
    if (nums.empty())
        return -1;
    int low = 0;
    int high = nums.size()-1;
    while (low <= high)
    {
        int mid = (low + high) / 2;
        if (nums[mid] < tar)
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
}

 

  这一类可以轻松的变形为查找最后一个小于目标值的数,怎么变呢。我们已经找到了第一个不小于目标值的数,那么再往前退一位,返回right - 1,就是最后一个小于目标值的数。

3、查找第一个大于目标值的数,可变形为查找最后一个不大于目标值的数

  这一类也比较常见,尤其是查找第一个大于目标值的数,在C++的STL也有专门的函数upper_bound,这里跟上面的那种情况的写法上很相似,只需要添加一个等号,将之前的 nums[mid] < target 变成 nums[mid] <= target,就这一个小小的变化,其实直接就改变了搜索的方向,使得在数组中有很多跟目标值相同的数字存在的情况下,返回最后一个相同的数字的下一个位置。比如在数组[2, 4, 5, 6, 9]中查找数字3,还是返回数字4的位置,这跟上面那查找方式返回的结果相同,因为数字4在此数组中既是第一个不小于目标值3的数,也是第一个大于目标值3的数,所以make sense;在数组[0, 1, 1, 1, 1]中查找数字1,就会返回坐标5,通过对比返回的坐标和数组的长度,我们就知道是否存在这样一个大于目标值的数。参见下面的代码:

int find(vector<int> &nums, int tar)
{
    if (nums.empty())
        return -1;
    int low = 0;
    int high = nums.size()-1;
    while (low <= high)
    {
        int mid = (low + high) / 2;
        if (nums[mid] <= tar)// 将这里的大于号,改为大于等于
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
}

 

  这一类可以轻松的变形为查找最后一个不大于目标值的数,怎么变呢。我们已经找到了第一个大于目标值的数,那么再往前退一位,返回right - 1,就是最后一个不大于目标值的数。比如在数组[0, 1, 1, 1, 1]中查找数字1,就会返回最后一个数字1的位置4,这在有些情况下是需要这么做的。

 

posted @ 2018-08-27 19:51  深度机器学习  阅读(898)  评论(0编辑  收藏  举报