二分查找及常见变体

简介: 二分查找及常见变体

概述


二分查找作为经典的查找算法,思想比较简单,日常使用频繁。每次编写二分相关代码,经常会出现左右区间混乱,不知道如何划分区间等问题,造成做不出题目。


代码分析


  • 区间的左右开闭问题: [0, length - 1]
  • 循环边界: while left < right,这样可以保证最终返回值left == right,随便返回哪个都可以
  • 区间[left.. right]可以划分为两种情况:
  • 分为[left..mid][mid+1..right],分别对应right = midleft = mid + 1
  • 分为[left..mid-1][mid..right],分别对应right = mid-1left = mid。在这种情况下,需要将mid = left + (right - left) / 2修改为 mid = left + (right - left + 1) / 2,否则将出现死循环。


例如 nums = [1,2,3,5]target = 5,若不修改 mid 计算,便会出现死循环


常见二分变体


查找第一个等于给定值的元素


第一个等于,逻辑上发生在数组左边,因此收缩右边界。


def firstEquals(nums, target):
    left, right = 0, len(nums) - 1 
    while left < right: 
        mid = left + (right - left)//2 # 防止溢出, //表示整除
        if nums[mid] < target: 
            left = mid + 1 
        else:
            right = mid # 收缩右边界
    return left 
复制代码


查找最后一个等于给定值的元素


最后一个等于,逻辑上发生在数组右边,因此收缩左边界。


def lastEquals(nums, target): 
    left, right = 0, len(nums) - 1
    mid = left + (right - left + 1) // 2
    while left < right:
        if nums[mid] > target:
            right = mid - 1
        else :
            left = mid
    return left
复制代码


查找第一个大于等于给定值的元素


第一个大于等于,逻辑上发生在数组左边,因此收缩右边界。


def firstLessEquals(nums, target): 
    left, right = 0, len(nums) - 1
    mid = left + (right - left) // 2
    while left < right:
        if nums[mid] < target:
            left = mid + 1
        else :
            right = mid
    return left
复制代码


查找最后一个小于等于给定值的元素


最后一个小于等于,逻辑上发生在数组右边,因此收缩左边界。


def firstLessEquals(nums, target): 
    left, right = 0, len(nums) - 1
    mid = left + (right - left + 1) // 2
    while left < right:
        if nums[mid] > target:
            right = mid - 1
        else :
            left = mid
    return left
复制代码


总结



通过多个角度的学习,自己暂且总结一个自用结论,当查找或者插入为第一个(偏左侧)时,收缩右边界right = mid;当为最后一个(偏右侧)时,收缩左边界left = mid


往期精彩文章



后语


如果大家感觉此文对你有一些帮助,希望能点个赞,鼓励鼓励阿包,阿包会不断努力的。另外如果本文章有问题,或者对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!


相关文章
|
机器学习/深度学习 存储 算法
决策树和随机森林在机器学习中的应用
在机器学习领域,决策树(Decision Tree)和随机森林(Random Forest)是两种非常流行且强大的分类和回归算法。它们通过模拟人类决策过程,将复杂的数据集分割成易于理解和处理的子集,从而实现对新数据的准确预测。
582 10
|
数据可视化 数据处理
结构化分析与设计
一、结构化分析与设计 结构化分析与设计(Structured Analysis and Design,简称SAD)是一种软件开发方法论,旨在通过分析和设计来构建高质量的软件系统。 结构化分析与设计的主要特点包括以下几点: 1. 结构化分析:结构化分析是通过对系统需求进行分析,将系统分解为若干个功能模块,并定义它们之间的关系和交互。在结构化分析中,常用的工具和技术包括数据流图(Data Flow Diagram,简称DFD)、数据字典(Data Dictionary)和实体关系图(Entity-Relationship Diagram,简称ERD)等。 2. 结构化设计:结构化设计是在结构化分析
1141 2
|
数据处理 Python
Pandas数据处理 | apply() 函数用法指南!
本文介绍一下关于 Pandas 中 apply() 函数的几个常见用法,apply() 函数的自由度较高,可以直接对 Series 或者 DataFrame 中元素进行逐元素遍历操作,方便且高效,具有类似于 Numpy 的特性。
|
5月前
|
存储 算法 Java
告别if-else臃肿代码!策略模式在业务中的落地实践与底层逻辑剖析
策略模式是Java后端开发中解决多分支逻辑问题的“利器”,其核心思想是“封装变化、依赖抽象”,通过抽象策略、具体策略、上下文(或工厂)三个核心角色,实现算法的灵活封装与扩展。
238 1
|
5月前
|
传感器 人工智能 算法
智能之巅:AI 如何重塑第六代战斗机
近日,两架“歼-36”六代机在成都双机同框引发热议。这不仅是航空技术的突破,更标志着AI深度融入空战体系。从群体智能到“忠诚僚机”,AI正重塑战争逻辑,推动中国空军迈向“算法为王”的智能时代。
480 0
|
数据库 Python
Python实践:从零开始构建你的第一个Web应用
使用Python和轻量级Web框架Flask,你可以轻松创建Web应用。先确保安装了Python,然后通过`pip install Flask`安装Flask。在`app.py`中编写基本的&quot;Hello, World!&quot;应用,定义路由`@app.route(&#39;/&#39;)`并运行`python app.py`启动服务器。扩展应用,可添加新路由显示当前时间,展示Flask处理动态内容的能力。开始你的Web开发之旅吧!【6月更文挑战第13天】
775 2
|
存储 安全 Linux
NFS使用TrueNAS SCALE的好处
从Linux自带的NFS转向TrueNAS SCALE,因其不仅提供块服务(iSCSI),还内置压缩功能。通过WEB界面开启SSH并设置Allow Password Authentication。安全配置方面,限制特定IP访问NFS输出。对比发现,对于文本文件,TrueNAS SCALE展现出显著的压缩优势,如日志文件压缩率接近90%,大大节省了存储空间,而对已压缩文件则无明显变化。这一转变有效优化了存储效率和安全性。
529 0
|
分布式计算 资源调度 Hadoop
【赵渝强老师】部署Hadoop的本地模式
本文介绍了Hadoop的目录结构及本地模式部署方法,包括解压安装、设置环境变量、配置Hadoop参数等步骤,并通过一个简单的WordCount程序示例,演示了如何在本地模式下运行MapReduce任务。
472 0
|
前端开发 数据可视化 算法
r语言Bootstrap自助法重采样构建统计量T抽样分布近似值可视化|代码分享
r语言Bootstrap自助法重采样构建统计量T抽样分布近似值可视化|代码分享