二分搜索法的探究与心得

引言

在计算机科学中,二分搜索(Binary Search)算法是一种在有序数组中查找特定元素的基本搜索技术。其优点在于高效的搜索速度,时间复杂度为 ( O(log n) ),这一点与时间复杂度为O(n) 的线性搜索法相比,效率提高了数个数量级。二分搜索的核心思想是“分而治之”,即将大问题分解为小问题来逐步解决。

二分搜索适用场景

二分搜索不仅适用于简单的有序数组查找,它也适用于任何可以通过单调性质进行决策的问题,如实数范围内的最优解搜索、概率问题中的阈值确定,以及在计算机图形学中的光线追踪技术等。掌握二分搜索不仅能提升算法效率,也有助于培养分析和解决问题的思维能力。

二分搜索的两种主流写法

传统上,二分搜索有两种流行的写法:左闭右闭 [left, right] 和左闭右开 [left, right)。左闭右闭写法的循环条件为 while (left <= right),而左闭右开写法的循环条件为 while (left < right)。这两种写法虽然在实现上略有不同,但都广泛应用于实践中。

左闭右闭写法

在这种写法中,搜索范围包括 leftright 指向的元素。每次循环将区间分为三部分:小于 mid 的元素、等于 mid 的元素和大于 mid 的元素。根据与 target 的比较结果,我们可以排除其中的一个区间。当 leftright 相遇时,循环结束,此时 leftright 指向相同的可能是 target 的位置。

左闭右开写法

而在左闭右开的写法中,right 指向的元素不包含在搜索范围内。这种方法的结束条件是 leftright 相邻,此时 left 指向的是最后一个不符合条件的元素,right 指向的是第一个符合条件的元素。

left + 1 != right 写法的探讨

这种写法本质上是左闭右开的一种变体。其优势在于处理边界的清晰性和减少了在循环中对 mid 的过度检查。

写法原理

这种写法的基本原理是保持 leftright 指针之间至少有一个元素的间隔。这样,left 永远指向不满足条件的最后一个元素,而 right 指向的是满足条件的第一个元素。当 leftright 相邻时,即 left + 1 == right,它们之间的元素就是我们要找的元素。

二分搜索写法的具体问题优势

left + 1 != right 方法在处理特定类型的问题时显示出其优势,如“查找第一个大于等于目标值的元素”或“查找最后一个小于等于目标值的元素”。在这些问题中,通过维护一个明确的未满足条件和已满足条件的界限,left + 1 != right 写法减少了对边界的额外检查,从而提高了代码的执行效率和可读性。

对边界的处理

使用 left + 1 != right 的方法,边界处理变得直观而简单。在传统的左闭右闭写法中,我们需要小心翼翼地处理 leftright 的更新条件,以避免出现无限循环或者错过目标元素。而在 left + 1 != right 的方法中,我们避免了这种直接更新 leftrightmid 的操作,因此减少了对边界处理的担忧。

对区间的考量

left + 1 != right 的二分搜索中,对区间的考量显得尤为重要。这种写法天然地支持左闭右开的区间操作,即 [left, right)。在每次循环中,我们将区间从 mid 处分割,并根据比较结果决定是将 left 移动到 mid,还是将 right 移动到 mid。由于我们总是保持 leftright 之间至少有一个元素的距离,因此可以确保 mid 永远不会与 leftright 重合,这减少了循环中可能的逻辑错误。

这种方法的一个显著优点是它使得二分搜索的每一步都更加明确。在传统的左闭右闭方法中,当我们找到 mid 满足条件时,我们可能需要额外的逻辑来确定是返回 mid,还是继续在左边或右边的区间中搜索。而在 left + 1 != right 方法中,这种情况得到了简化:我们总是在确信没有遗漏任何可能的元素时才结束循环。

细节解析

1)迭代的过程

 整个二分的过程是一个不断迭代区间的过程,并且 红色游标 指向的元素始终是 红色 的;绿色游标 指向的元素始终是 绿色 的。迭代的过程就是不断向 红绿边界 逼近的过程。

2)结束条件

迭代结束时,红色游标 和 绿色游标 刚好指向 红绿边界,且区间长度为 2。

3)游标初始值

为什么 红色游标 初始值为 −1,绿色游标 初始值为 n ?

  能否将 红色游标 初始化为 0,绿色游标 初始化为 n−1 ? 答案是否定的,试想一下,如果数据元素都是绿色,红色游标 初始化为 0 就违背了 " 红色游标 指向的元素始终是 红色 的 " 这个条件;反之,如果元素都是红色的,也有类似问题。

4)中点位置

5)死循环

上面的程序模板是否会进入死循环?

  我们可以这么来看,当区间为 2 时,循环结束。当区间为 3 时,它一定可以变成区间为 2 的情况,当区间为4时,一定可以变成区间为 2 或者 3 的情况,也就是任何一种情况下,区间一定会减小,并且当等于 2 时,循环结束。所以不会造成死循环。

实践中的应用

在实际应用中,left + 1 != right 的方法尤其适合于寻找区间的极值问题,例如寻找旋转排序数组中的最小元素,或者在一个由两种元素(如“红色”和“绿色”)组成的数组中找到颜色变化的边界。在这些情况下,这种二分搜索方法能够清晰地定位到边界点,而不需要额外的边界检查。

代码模板

public int binarySearch(int[] nums, int target) {int left = -1, right = nums.length; // 初始化left为-1,right为数组长度while (left + 1 != right) { // 当左右指针相邻时停止int mid = left + ((right - left) >> 1); // 计算中点if (check()) { left = mid; // 更新左(或右)指针} else { right = mid; // 更新左指针}}// 循环结束时,left 为指向第一个绿色元素(或者 right 为指向最后一个红色元素)return left;
}

边界情况讨论

在数组的开始和结束位置,left + 1 != right 方法通过简化的逻辑清晰地处理了边界情况。尤其是在数组的结束位置,这种写法自然而然地避免了数组越界的风险,这是因为它始终保持 right 指针在数组范围内。

优势总结

left + 1 != right 的二分搜索法在多个方面展现出它的优势:

  • 精确的边界控制:通过保持 leftright 之间的间隔,这种方法减少了边界值的特殊处理,使得代码更加简洁。
  • 逻辑一致性:更新 leftright 变得一致和直观,不再需要额外的 if 判断来避免包含或排除中点值。
  • 减少错误:由于不需要处理 mid - 1mid + 1,此方法减少了由于错误更新索引而导致的无限循环或漏掉正确元素的风险。
  • 清晰的搜索意图:代码清晰地表达了搜索意图,特别是在区间分割的策略上,这对于阅读和维护代码的人来说是一个巨大的优势。
  • 可扩展性:这种写法易于扩展到更复杂的场景,如多维数组的二分搜索,或者需要进行复杂判断逻辑的问题。

与传统二分的对比

与传统的二分搜索方法相比,left + 1 != right 的写法在概念上更为简单和直观,尤其是对于边界条件的处理。在传统的二分搜索中,如果不小心处理,很容易在边界条件上出现错误,比如忘记了 mid - 1mid + 1,或者在 while 循环的条件中使用了错误的比较运算符。而在 left + 1 != right 的方法中,这些问题都不复存在。我们可以用一种更加一致和安全的方式来处理搜索逻辑。

结论

left + 1 != right 的二分搜索方法以其简洁的边界处理和清晰的逻辑流程,提供了一种新颖而有效的解决问题的方法。它不仅加强了对二分搜索的理解,还扩展了这一算法的应用范围,使得开发者能够更容易地实现和维护相关的算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/464949.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud Hystrix 参数配置、简单使用、DashBoard

Spring Cloud Hystrix 文章目录 Spring Cloud Hystrix一、Hystrix 服务降级二、Hystrix使用示例三、OpenFeign Hystrix四、Hystrix参数HystrixCommand.Setter核心参数Command PropertiesFallback降级配置Circuit Breaker 熔断器配置Metrix 健康统计配置Request Context 相关参数…

python 基础知识点(蓝桥杯python科目个人复习计划35)

今日复习计划&#xff1a;阶段总结&#xff08;新年贺礼&#xff09; 1.python简介&#xff08;定义&#xff0c;优点&#xff0c;缺点&#xff0c;应用领域&#xff09; python&#xff1a;一种广泛使用的解释型&#xff0c;高级和通用的编程语言 python极简&#xff0c;生…

python执行js代码

1. Python执行JavaScript代码 假如在爬虫逆向分析时&#xff0c;发现某个js加密算法比较繁琐&#xff0c;用Python还原同样的算法比较费劲。此时&#xff0c;可以不必使用Python还原&#xff0c;而是利用Python去直接调用JavaScript中定义的功能。 想实现Python调用JavaScrip…

六招,搞定大气上档次的可视化界面!有图有真相。

以下是一些设计可视化图表更加美观大气的建议&#xff1a; 选择合适的颜色&#xff1a; 颜色可以帮助人们更好地理解和记忆数据。选择颜色时&#xff0c;应该考虑颜色的对比度、亮度和饱和度等因素&#xff0c;同时也要考虑颜色的文化含义和情感效果。 使用合适的字体&#x…

【动态规划】1301. 最大得分的路径数目

作者推荐 【动态规划】【前缀和】【C算法】LCP 57. 打地鼠 本文涉及知识点 动态规划汇总 LeetCoce1301. 最大得分的路径数目 给你一个正方形字符数组 board &#xff0c;你从数组最右下方的字符 ‘S’ 出发。 你的目标是到达数组最左上角的字符 ‘E’ &#xff0c;数组剩余…

嵌入式系统的前景:未来智能汽车

&#xff08;本文为简单介绍&#xff0c;个人的观点仅供参考&#xff09; 智能汽车时代已经来临!未来十年,我们的汽车将变得越来越智能化。各大汽车公司在研发自动驾驶技术,目标是实现真正的无人驾驶。要实现这一目标,嵌入式系统将发挥关键作用。 简单来说,嵌入式系统就是在汽…

C++引用(内含和指针的对比)

1.引用的概念 概念&#xff1a;引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b;&#xff08;&这个符…

###C语言程序设计-----C语言学习(11)#数据的存储和基本数据类型

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 一. 数据的存储 1.整型数据的存储 计算机处理的所有信息都以二进制形式表示…

Python:解析获取连续的重叠对pairwise

简介&#xff1a;pairwise函数&#xff0c;返回从输入迭代器获取的重叠对的迭代器&#xff0c;是Python 3.10 新特性&#xff0c;表示一个迭代器从对象中获取连续的重叠对&#xff0c;在某些场景中可以优化代码运行效率。pairwise 函数是一种用于处理列表中元素之间配对操作的通…

基于Python的信息加密解密网站设计与实现【源码+论文+演示视频+包运行成功】

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java、Python等技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; …

VsCode中常用的正则表达式操作

在vscode中可以使用正则表达式来进行搜索内容&#xff0c;极大的方便了我们对大量数据中需要查看的信息进行筛选&#xff0c;使用正则搜索时点击 .* 此文章会持续补充常用的正则操作 1.光标选中搜索到的内容 将搜索的内容进行全选&#xff0c;举例&#xff1a;在如下文件中我需…

Unity类银河恶魔城学习记录3-6 Finalize BattleState源代码 P52

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Enemy.cs using System.Collections; using System.Collections.Generic; …