首页 > 其他分享 >二分查找

二分查找

时间:2023-06-05 20:45:26浏览次数:50  
标签:二分 right target middle 查找 目标值 左闭 left

思路

二分法的前提是数组有序。另外,当数组中存在重复元素时,最后返回的下标可能不唯一,具体实现不同,可能导致最后结果也不同。
image

left和right代表搜索区域的上下界,其基本思路就是把数组搜索区域分成两个区域,通过middle指针判别目标值属于哪个区域,然后在目标值所在的区域进一步二分,逐渐缩小范围并最后找到。

复杂度

  • 时间复杂度:o(logn)
  • 空间复杂度:o(n)(原地修改,所以空间消耗就是数组本身以及三个指针)

具体代码实现

代码实现难点主要在于:

  • 循环的跳出条件到底是 left<right 还是 left<=right ;
  • 当目标值比 middle 所指的值小时,表示在 middle 左边的区域,此时 right 到底时 middle 还是 middle-1
  • 当目标值比 middle 所指的值大时,表示在 middle 右边的区域,此时 left 到底时 middle 还是 middle+1

一般在网上或者课本里所说的实现方法有两种,分别是左闭右闭([left, right])左闭右开([left, right)),这里我主要介绍第一种左闭右闭的实现,因为当你理解第一种的实现后,第二种就很简单啦。

左闭右闭是指left和right所指向的值也属于搜索区域内,于是此时循环的跳出条件应是left<=right,因为left=right是有意义的,表示此时的搜索区域就是当前两个指针所指的那个值。同理左闭右开跳出循环的条件应是left<right,因为当left=right时,搜索区间的上界是right的前一个值,故此时实际的搜索区间是没有意义的。

另外,左闭右闭时,当目标值比 middle 所指的值小时,right=middle-1,因为right所指的值时搜索区间的上界;同理,当目标值比 middle 所指的值大时,left=middle+1。

于是真个代码实现思路如下:

int search(vector<int>& nums, int target) 
{
    int left = 0;
    int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
    while (left <= right) // 当left==right,区间[left, right]依然有效,所以用 <=
    {
        int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
        if (nums[middle] > target)
        {
            right = middle - 1; // target 在左区间,所以[left, middle - 1]
        }
        else if (nums[middle] < target)
        {
            left = middle + 1; // target 在右区间,所以[middle + 1, right]
        }
        else // nums[middle] == target
        {
            return middle; // 数组中找到目标值,直接返回下标
        }
    }
    // 未找到目标值
    return -1;
}

相关leetcode题

34.在排序数组中查找元素的第一个和最后一个位置
35.搜索插入位置
704.二分查找

标签:二分,right,target,middle,查找,目标值,左闭,left
From: https://www.cnblogs.com/sunjuil/p/17458891.html

相关文章

  • Python 子类继承了多个父类 , MRO查找调用方法
      在Python中,如果一个子类继承了多个父类,而这些父类中都有同名的方法或属性,那么子类在调用这个方法或属性时,会按照MRO(MethodResolutionOrder,方法解析顺序)的规则进行查找和调用。在Python中,MRO的顺序是由C3算法计算出来的。C3算法是一种基于拓扑排序和合并的算法,用......
  • 二分法
    使用条件有序数组元素不重复区间设置左闭右闭:左右区间边界都要在数组的索引有效范围内(left=0,right=数组长度-1)判断条件left(左边界)<=right(右边界)左闭右开左区间边界在数组的有效索引范围内,右边界不在(left=0,right=数组长度)判断条件left(左边界)<right(右......
  • 二分查找的循环不变量全面解析
    二分查找的循环不变量全面解析原理二分查找的bug模版二分法变种寻找左侧/右侧元素的二分查找查找大于key的最小值upper查找小于key的最大值lower大于等于key的最小索引lower_ceil实践69.x的平方根215.数组中的第K个最大元素704.二分查找875.爱吃香蕉的珂珂1011.在......
  • 如何查找Black Hat会议文章
    BlackHat官网:https://www.blackhat.com/查看BlackHat历史文章:选择会议:选择主题:或者可以Ctrl+F搜索具体的文章......
  • 查找目录下的所有文件中是否含有某个字符串 linux
    评:查找目录下的所有文件中是否含有某个字符串find.|xargsgrep-ri"IBM"查找目录下的所有文件中是否含有某个字符串,并且只打印出文件名find.|xargsgrep-ri"IBM"-l1.正则表达式(1)正则表达式一般用来描述文本模式的特殊用法,由普通字符(例如字符a-z)以及特殊字符(称......
  • NOI / 1.9编程基础之顺序查找
    4:谁拿了最多奖学金描述某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:1)    院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;2)    五四奖学金,每人4000元,期末平均成绩高于......
  • NOI / 1.9编程基础之顺序查找 05:最大值和最小值的差
    描述输出一个整数序列中最大的数和最小的数的差。输入第一行为M,表示整数个数,整数个数不会大于10000;第二行为M个整数,以空格隔开,每个整数的绝对值不会大于10000。输出输出M个数中最大值和最小值的差。样例输入525742样例输出5题意输入M,表示整数个数,再输入M个整......
  • 二分图
    存在一个无向图,图中有\(n\)个节点。其中每个节点都有一个介于\(0\)到\(n-1\)之间的唯一编号。给你一个二维数组\(graph\),其中\(graph[u]\)是一个节点数组,由节点\(u\)的邻接节点组成。形式上,对于 \(graph[u]\)中的每个\(v\),都存在一条位于节点\(u\)和节点\(......
  • windows cmd 命令中使用grep 查找
    有时候我们想使用netstat命令查询具体哪个端口,但是windowsdos自带没有像linux哪样的grep,我们就需要使用第三方插件。下载地址:https://gnuwin32.sourceforge.net/packages/grep.htm 如果无法下载可使用百度网盘下载:链接:https://pan.baidu.com/s/1qpJZ362VBjgWfqJdL24LIA?p......
  • 2023.6.2linux系统文件查找
    03.Linux系统⽂件查找⽂件查找概述find名称查找find⼤⼩查找find时间查找find⽤户查找find类型查找find权限查找find处理动作Authorvx:WingspanGo⽂件查找概述Linux系统中的find命令在查找⽂件时⾮常有⽤⽽且⽅便。它可以根据不同的条件来进⾏查找⽂件:例如⽂件......