ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于二分搜索 简单、左侧区间、右侧区间

2022-04-16 10:00:50  阅读:205  来源: 互联网

标签:二分 target nums int lo mid hi 区间 右侧


4月15号阅文一面,问完八股之后被问到了二分搜索,我啪的一下就写出来了,很快啊!面试官也很高兴,想加大一点难度,让我写一下搜索左侧区间的二分搜索。
什么是搜索左侧区间的二分搜索呢?比如一个排序数组里有某个元素重复出现了多次,我们的二分搜索必须每次返回这个元素第一次出现的位置。比如数组 0, 1, 2, 4, 4, 4, 6, 7, 9 输入target = 4 时我们的函数应该返回3
然而啊,我大意了,对这道题的理解还不够深刻,面试的时候写的不对。虽然被面试官指出了问题也改正了,但是面试凉凉了。大家要学好二分搜索啊!不能像我一样。

从最基础的二分搜索谈起

int binSearch(vector<int> &nums, int target){
    int lo = 0, hi = nums.size() - 1; // 将hi设为这个值,意味着搜索期间为闭区间[lo, hi]
    while(lo < hi){ // 因为区间是闭区间,跳出循环的条件是lo < hi 而不是 <=
        int mid = lo + (hi - lo) / 2;
        if(nums[mid] == target){
            return mid;
        }
        else if(nums[mid] < target){ // 中点值比目标值小,说明目标在右侧区间
            lo = mid + 1;
        }
        else if(nums[mid] > target){ // 中点值比目标值大,说明目标在左侧区间
            hi = mid - 1;
        }
        // 小细节:多写几个else if ,而不是直接一个else 这样可以方便对代码的查看和思路的疏通。
    }
    return -1; // 没有找到,返回-1
}

几个比较重要的点已经在注释中标注了,最简单的二分查找在遇到有重复数字的数组时,可能会返回其中符合条件的随机一个位置。因此,如果我们要返回区间左侧或者右侧坐标,需要对其稍稍改变。

返回区间左侧或右侧坐标的二分查找

int findLeft(vector<int>& nums, int target){
    int lo = 0, hi = nums.size() - 1;
    while(lo <= hi){
        int mid = lo + (hi - lo) / 2;
        if(nums[mid] == target)
            hi = mid - 1; //注意
        else if(nums[mid] > target)
            hi = mid - 1;
        else if(nums[mid] < target)
            lo = mid + 1;
    }

    if(lo >= nums.size() || nums[lo] != target) return -1;  //lo可能在合法区间之外(当任意nums[i] < target 均成立时),也可能nums数组中不存在target。
    return lo; 
}

注意,当我们的nums[mid] == target已经成立时,不要直接返回,而是继续收缩区间右侧,令其缩减到目标值出现位置的左侧。我们跳出循环的条件一定是lo == hi - 1, 也就是说,跳出循环时,lo的位置即指向nums[mid] == target 最后一次成立的位置。

搜索右侧区间的算法同理,此处供参考。

int findRight(vector<int>& nums, int target){
    int lo = 0, hi = nums.size() - 1;
    while(lo <= hi){
        int mid = lo + (hi - lo) / 2;
        if(nums[mid] == target)
            lo = mid + 1;
        else if(nums[mid] > target)
            hi = mid - 1;
        else if(nums[mid] < target)
            lo = mid + 1;
    }

    if(hi < 0 || nums[hi] != target) return -1;
    return hi;
}

推荐阅读:labuladong:我写了首诗,让你闭着眼睛也能写对二分搜索
推荐练习: Leetcode 34

标签:二分,target,nums,int,lo,mid,hi,区间,右侧
来源: https://www.cnblogs.com/wstnl/p/16152026.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有