当前位置: 首页 > news >正文

【基础算法】二分查找的多种写法

前言

        在算法竞赛中,二分查找使用的频率是非常高的,对于C++选手而言,有STL中自带的lower_bound和upper_bound二分查找,可以很方便的进行二分查找。但是非C++选手、或者需要自定义多条件查找的情况需要自己写一个二分,本文对几种常见的二分查找写法进行讲解。

        本文使用的编程语言为Java,但代码比较好理解其他语言选手也可以查看本文来学习二分相关内容。


二分查找

        二分查找,也称折半查找,是一种可以在有序序列上进行快速查找的算法,时间复杂度是O(logn)

        常见的二分查找类型,有以下两种:

  • 查找目标值在序列中不小于目标值的第一个元素(同lower_bound,以此查到第一个位置)。

  • 查找目标值在序列中第一个大于目标值的元素(同upper_bound,以此查找到最后一个出现的位置)。

        在设置区间的时候,根据写法的不同分为下面几种:

  • 左闭右闭。

  • 左闭右开。

        根据最终获取答案的写法,又分为下面两种:

  • 在左右指针处取值。

  • 设置额外变量取值。

        本文将分不同情况,写出不同情况下的二分查找模板,帮助大家理解学习。


查找目标值在序列中不小于目标值的第一个元素

        也就是实现一个STL中的lower_bound。

左闭右闭版

/*** [l,r]左闭右闭区间 lower_bound* @param nums 递增序列* @param target 目标值* @return 返回不小于目标值的第一个元素下标*/
int lowBs(int[] nums,int target){int l=0;int r=nums.length-1;while(l<=r){int mid=l+(r-l>>1);if(nums[mid]<target){l=mid+1;}else{r=mid-1;}}return l;
}

左闭右开版

/*** [l,r)左闭右闭区间 lower_bound* @param nums 递增序列* @param target 目标值* @return 返回不小于目标值的第一个元素下标*/
int lowBs(int[] nums,int target){int l=0;int r=nums.length;while(l<r){int mid=l+(r-l>>1);if(nums[mid]<target){l=mid+1;}else{r=mid;}}return l;
}

查找目标值在序列中第一个大于目标值的元素

        也就是实现一个STL中的upper_bound。

左闭右闭版

/***  [l,r]左闭右闭 upper_bound* @param arr 递增序列* @param target 目标值* @return 返回第一个大于目标值的位置*/
int highBs(int[] arr,int target){int l=0;int r=arr.length - 1;while(l<=r){int mid=l+(r-l>>1);if(arr[mid]<=target){l=mid+1;}else{r=mid-1;}}return l;
}

左闭右开版

/***  [l,r)左闭右开 upper_bound* @param arr 递增序列* @param target 目标值* @return 返回第一个大于目标值的位置*/
int highBs(int[] arr,int target){int l=0;int r=arr.length;while(l<r){int mid=l+(r-l>>1);if(arr[mid]<=target){l=mid+1;}else{r=mid;}}return l;
}

易错问题和常见问题总结

一、需要注意区间定义和终止条件是否匹配正确

  • 左闭右闭:初始化 r = nums.length-1,终止条件 while (l <= r)

  • 左闭右开:初始化 r = nums.length,终止条件 while (l < r)

二、指针更新是否正确

  • 左闭右闭:r = mid - 1l = mid + 1

  • 左闭右开:r = mid

三、运算符优先级

        应写为:int mid = l + ( r - l >> 1)

?为什么不能写为 l + r >> 1

        如果可以保证l+r不会溢出的话,其实这样写也可以,但是为了保证不出现数据溢出,更加推荐写上面的形式。

相关文章:

  • rabbitMQ如何确保消息不会丢失
  • Qt通过QXlsx库文件写入到excl文件,读取excl文件
  • 解决The‘InnoDB’feature is disabled; you need MySQL built with ‘InnoDB’ to have it
  • 计算几何(简单旋转卡壳)2024昆明邀请赛
  • Expected SARSA算法详解:python 从零实现
  • 仿腾讯会议——注册登录实现
  • Day.js和Moment.js对比,日期时间库怎么选?
  • SALOME源码分析: ParaVis
  • 【连载9】基础智能体的进展与挑战综述-行动系统
  • 基于STM32的带恒温系统智能外卖柜设计
  • B站Michale_ee——ESP32_IDF SDK——FreeRTOS_5 事件组同步与等待
  • 如何让模型聪明地选择特征:一种“蒸馏及选择”的方法
  • 使用 Tesseract 实现藏文OCR
  • 大数据面试问答-数据湖
  • Codex CLI轻量级 AI 编程智能体 :openai又放大招了
  • 正弦波、方波、三角波和锯齿波信号发生器——Multisim电路仿真
  • 在pycharm profession 2020.3上安装使用xlwings
  • Ubuntu 安装 MySQL8
  • 游戏通用活动框架
  • C++拷贝构造函数详解
  • 人民日报头版头条:青春为中国式现代化挺膺担当
  • 哈马斯:愿与以色列达成为期5年的停火协议
  • 苏州一直升机坠落致1死4伤,事故调查正展开
  • 巴菲特执掌60年,伯克希尔市值如何增长5.5万倍?详解五大经典投资案例
  • 韩国前国务总理韩德洙正式宣布参加总统选举
  • 体坛联播|曼联一只脚迈进欧联杯决赛,赵心童4比4奥沙利文