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

搜索--二分查找

二分查找,它是基于分治策略的高效搜索算法,利用数据的有序性,每轮缩小一半搜索范围,直至找到目标元素或搜索区间为空为止。
优势和局限:二分查找仅适用于有序数据的数组(需跳跃式(非连续地)访问元);其时间复杂度通常为 O(logn)O(\mathrm{log} n)O(logn)


场景1:给定一个数组 nums,其数组没有重复元素且元素按从小到大排序,数组长度为 n;在数组查找元素 target 并返回对应的下标,若数组不包含目标元素,就返回 −1-11
算法流程
(1)初始化两个指针 i=0j=n-1,分别指向数组的首元素和尾元素,代表搜索区间 [0,n−1][0, n-1][0,n1]。此时我们规定:下标严格小于 i 的元素一定小于 target,而下标严格大于 j 的元素一定大于 target
(2)满足 i <= j 的条件下,循环执行以下两步:
 (2.1)计算中点索引 m=⌊(i+j)/2⌋m = \lfloor(i+j)/2\rfloorm=⌊(i+j)/2
 (2.2)判断 nums[m]target 的大小关系,分为以下三种情况:
   a、当 nums[m] = target 时,说明找到 target,因此返回索引 m
   b、当 nums[m] < target 时,说明 target 在区间 [m+1,j][m+1, j][m+1,j] 中,因此执行 i=m+1i = m + 1i=m+1
   c、当 nums[m] > target 时,说明 target 在区间 [i,m−1][i, m-1][i,m1] 中,因此执行 j=m−1j = m - 1j=m1

在这个过程中,区间大小会不断减少,知道遇到目标元素或者为空(i > j),结束循环,查找结束。
情况 b 中,修改指针 i 的取值,说明区间 [0,i−1][0, i-1][0,i1] 的元素均小于 target(此时 i=m+1i=m+1i=m+1),满足上述规定;
情况 c 中,修改指针 j 的取值,说明区间 [j+1,n−1][j+1, n-1][j+1,n1] 的元素均大于 target(此时 j=m−1j=m-1j=m1),满足上述规定;
当出现 i = j 时,说明待判断的元素只剩下一个:若是目标值,则直接返回下标,若不是目标值,根据其与 target 关系修改指针的值,进而查找范围为空。

def binarySearch(nums, target):n = len(nums)i, j = 0, n-1while i <= j:m = i + (j-i)//2if nums[m] < target:i = m+1elif nums[m] > target:j = m-1else:return mreturn -1

场景2:在上述数组的基础上,假设数组中存在多个 target,则上述的二分查找只能返回其中一个的索引,无法确定该元素的左边和右边还有多少 target
为此,扩展上面的二分查找代码,使其能找到第一个 target,并返回对应的下标。

算法流程:整体流程保持不变,初始化 i=0j=n-1;接着,每轮循环中计算索引 mmm,再判断 nums[m]target 的关系:
(1) 当 nums[m] > targetnums[m] < target 时,说明还没有找到目标值,则跟上述一样,修改指针 ij,使其缩小范围;
(2) 当 nums[m] == target 时,说明找到目标元素,可采用 j=m−1j=m-1j=m1 来缩小搜索区间,这可保持小于 target 的元素在 [0,m−1][0, m-1][0,m1] 中,而指针 j 向着小于 target 元素靠近
完成循环后,i 指向最左边的 target,而 j 指向首个小于 target 的元素。最终,返回索引 i

在这个过程中规定:下标小于 i 的元素一定小于 target,而下标大于 j 的元素是大于等于 target

def binarySearch2(nums, target):"""二分查找(存在重复元素)"""n = len(nums)i, j = 0, n-1while i <= j:m = i + (j-i)//2if nums[m] < target:i = m+1elif nums[m] > target:j = m-1else:j = m-1return i

参考:《Hello 算法》

http://www.lryc.cn/news/600037.html

相关文章:

  • haproxy七层代理(实验)
  • Excel导入数据库-01.构思
  • 4麦 360度定位
  • 力扣 hot100 Day55
  • lock 和 synchronized 区别
  • 基于粒子群优化的PID控制在药液流量控制系统中的应用
  • nacos的配置中心
  • 学习嵌入式的第二十九天-数据结构-(2025.7.16)线程控制:互斥与同步
  • php语法--foreach和in_array的使用
  • 环境变量-进程概念(7)
  • PowerDesigner安装教程(附加安装包)PowerDesigner详细安装教程PowerDesigner 16.6 最新版安装教程
  • 7.文件操作:让程序读写文件 [特殊字符]
  • haproxy七层代理(原理)
  • 【07】C#入门到精通——C# 生成dll库 C#添加现有DLL C#调用自己生成的dll库
  • Typecho多语言解决方案:从插件到主题的完整实现
  • CANoe入门(11)-- 诊断模块
  • SpringBoot学习路径--SpringBoot的简单介绍和项目搭建
  • c++注意点(13)----设计模式(抽象工厂)
  • 医疗器械:DFEMA和PFEMA
  • 从数据脱敏到SHAP解释:用Streamlit+XGBoost构建可复现的川崎病诊断系统
  • [NLP]一个完整的 UPF 文件示例
  • 文心4.5横向对标全球大模型:技术突破与应用前景深度分析
  • OSPF 路由协议多区域
  • 利用Dify实现应用日志关键信息提取之实践
  • 九联UNT413AS_晶晨S905L3S芯片_2+8G_安卓9.0_线刷固件包
  • RK3588 HDMI-RX 驱动、RGA 加速与 OpenCV GStreamer 支持完整指南
  • React性能优化终极指南:memo、useCallback、useMemo全解析
  • 堆(Heap)优先级队列(Priority Queue)
  • python基础:request模块简介与安装、基本使用,如何发送get请求响应数据,response属性与请求头
  • 《计算机组成原理与汇编语言程序设计》实验报告一 基本数字逻辑及汉字显示