zoukankan      html  css  js  c++  java
  • 代码题(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,这在有些情况下是需要这么做的。

  • 相关阅读:
    网站优化,dns预解析,解析缓存
    dos命名重启或关闭远程服务器
    IIS 常见问题集记录
    EF 基础提供程序在 Open 上失败
    flexbox学习
    svn post-commit 同步
    备份
    log4net 2.0.4有问题,AdoNetAppender会报错
    signalr 配置错误跟踪
    Facebook的Web开发三板斧:React.js、Relay和GraphQL
  • 原文地址:https://www.cnblogs.com/eilearn/p/9544371.html
Copyright © 2011-2022 走看看