当前位置: 首页 > 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不会溢出的话,其实这样写也可以,但是为了保证不出现数据溢出,更加推荐写上面的形式。

http://www.xdnf.cn/news/259651.html

相关文章:

  • 通过组策略使能长路径
  • 我的创作纪念日,5.1特别篇
  • 英一真题阅读单词笔记 20-21年
  • 第 1 篇:起点的选择:为何需要超越数组与链表?
  • 深度解析 Let‘s Encrypt 证书申请:从核心概念到实战避坑指南
  • Open3d函数 认识
  • Java实现区间合并算法详解
  • 【AI提示词】奥卡姆剃刀思维模型专家
  • 基于随机森林的糖尿病预测模型研究应用(python)
  • Qt编译报错:Unexpected compiler version, expected Clang 18.0.0 or newer——Qt安装MSVC编译器
  • 一种快速计算OTA PSRR的方法(Ⅱ)
  • 银河麒麟操作系统QT程序打包,使用 linuxdeployqt 自动打包
  • IntelliJ IDEA 保姆级使用教程
  • ALiBi (Attention with Linear Biases) 优化LLM 模型注意力
  • 每日一题洛谷P8635 [蓝桥杯 2016 省 AB] 四平方和c++
  • 抽奖算法场景
  • Cherry Studio的MCP协议集成与应用实践:从本地工具到云端服务的智能交互
  • 【2025最新】MySQL的各种锁有哪些?各种索引优化有哪些(索引覆盖,索引下推,索引跳跃扫描等)?怎么设计索引?排查索引?
  • P20:Inception v3算法实战与解析
  • ThreadLocal理解
  • Manus AI多语言手写识别技术解析
  • C语言-指针(二)
  • Linux diff 命令使用详解
  • flux_train_network的参数
  • new的几种形式
  • 深入理解 C++ 变量:从基础到高级应用
  • 5月2日日记
  • (六——下)RestAPI 毛子(Http resilience/Refit/游标分页/异步大文件上传)
  • Linux-常用监控工具
  • 第 12 届蓝桥杯 C++ 青少组中 / 高级组省赛 2021 年 4 月 24 日真题(选择题)