《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》

《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》
前引:算法面试中,二分查找是 “高频考点” 之一,它不仅能考察求职者的逻辑思维,还能检验对时间复杂度优化的理解。而在实际开发中,二分查找更是处理 “有序数据查找” 问题的最优解无论是缓存查找、数据索引,还是参数优化,都能看到它的身影。但很多开发者对二分查找的理解停留在 “基础用法”,忽略了其在复杂场景下的拓展应用,也未能规避常见的边界错误。本文将结合面试真题和实战案例,全面解析二分查找的原理、优化技巧、场景延伸,帮你既能轻松应对面试,又能在实际开发中高效运用,真正发挥二分查找的 “效率优势”!

目录

【一】“二分”算法原理剖析

【二】简单的二分查找

(1)题目链接

(2)算法解析

【三】找目标范围

(1)题目链接

(2)算法解析

(3)代码

【四】搜索插入位置

(1)题目链接

(2)算法解析

(3)代码

【五】寻找旋转数组中的最小值

(1)题目链接

(2)算法解析

(3)代码


【一】“二分”算法原理剖析

“二分”的刻板印象就是需要目标有序,即0,1,2,3,4,5.....但是“二分”的本质:通过目标值排除达到一半的区间,解决传统的从头到尾的遍历查找,只要目标数据与目标值满足一定的大小关系,下面是三套二分模板,我们开始推:

第一套模版:

 int left=0,right=nums.size()-1; int media=0; //找左端点 while(left<right) { media = (right+left)/2; if(nums[media]>target)right=media-1; else if(nums[media]<target)left=media+1; }

第二套模板:

推论:假设找target连续的区间(找左端点)

首先看左边区间:如果mid落在左边的区间,那么mid不可能命中到8,left=mid+1

                             8在右边的一坨中,那么mid不能超过这个区间(竖划线),right=mid

                             mid的中值计算应该为:left+(right-left)/2(计算左端点)

                             循环条件应该是:left<right,如果等于,会由于判断条件导致循环

现象:如果mid落在左边,就必须超过竖划线收缩;在右边应该不断收缩,但是不能超过竖划线

 int left=0,right=nums.size()-1; int media=0; //找左端点 while(left<right) { media = left+(right-left)/2; if(nums[media]>=target)right=media; else if(nums[media]<target)left=media+1; }

第三套模板:

推论:假设找target连续的区间(找右端点)

首先看左边区间:如果mid落在左边的区间,那么mid可能命中到8,left=mid

                             mid落在右边的一坨,那么mid不能超过这个区间,right=mid-1

                             mid的中值计算应该为:left+(right-left+1)/2(计算右端点)

                             循环条件应该是:left<right,如果等于,会由于判断条件导致循环

现象:如果mid落在左边,就不能超过竖划线收缩;在右边应该不断收缩,必须要超过竖划线

 //找右端点 left=0,right=nums.size()-1; while(left<right) { media = left+(right-left+1)/2; if(nums[media]>target)right=media-1; else if(nums[media]<=target)left=media; }

【二】简单的二分查找

(1)题目链接

https://leetcode.cn/problems/binary-search

(2)算法解析

这题大家套“二分算法原理剖析”的第一套模板即可

【三】找目标范围

(1)题目链接

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array

(2)算法解析

暴力解法:遍历数组,找先目标值,再看是否有连续的目标值,记录它们的下标即可

算法解析:(以下是找的到target的情况,需要判断找不到的情况)

首先找左端点:

以上图为例,具备完美的边界(二段性),左边界的8比左边的0,3,5,6都要大,如果mid落在边界左边,不管怎样都要找比mid位置大的数,所以如果小于目标值,left=mid+1

那么如果mid落在>=8(左边界的8)的位置,right不应该跳过且收缩,所以right=mid

其次是右端点:

以上图为例,具备完美的边界(二段性),同理:

如果落在最右边8的左边,那么left不能跳过这段区间,只能是left=mid,不断收缩

如果落在最右边8的右边,那么right最终肯定要跳过才行,所以right=mid-1,跳过+收缩

(3)代码
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { if(nums.size()==0)return {-1,-1}; vector<int> V; int left=0,right=nums.size()-1; int media=0; //找左端点 while(left<right) { media = left+(right-left)/2; if(nums[media]>=target)right=media; else if(nums[media]<target)left=media+1; } if(nums[left]==target) { V.push_back(left); } else//如果找不到 { V.push_back(-1); } //找右端点 left=0,right=nums.size()-1; while(left<right) { media = left+(right-left+1)/2; if(nums[media]>target)right=media-1; else if(nums[media]<=target)left=media; } if(nums[left]==target) { V.push_back(left); } else//如果找不到 { V.push_back(-1); } return V; } };

【四】搜索插入位置

(1)题目链接

https://leetcode.cn/problems/search-insert-position

(2)算法解析

对于有二段线的数组+目标值的,我们采用二分的方法,下面是思路,采用第几套模板:

我们观察这两组值:

nums = [1,3,5,6], target = 2

nums = [1,3,5,6], target = 7

可以看到:找的都是稍大的位置,比如第一组目标位置是1号下标,那么如果nums[i]<2,有没有可能?完全没有,所以如果算出的目标值比小,那么left=mid+1,只要确定了一边,那么另一边就出来了,right=mid,循环条件是left<right,最后肯定是left和right相遇出循环,此时判断是不是目标值,再做返回值处理

(3)代码
class Solution { public: int searchInsert(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; int media = 0; //找左端点 while (left < right) { media = left + (right - left) / 2; if (nums[media] >= target)right = media; else if (nums[media] < target)left = media + 1; } if(nums[left]<target)return left+1; return left; } };

【五】寻找旋转数组中的最小值

(1)题目链接

https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array

(2)算法解析

对于数组中找值的这类题目,我们先看有没有二段性,很明显有:数组中最小的元素

每旋转一次是把最后一个值拿到前面来,因此,就像一个蜿蜒的山峰:

因此可以以nums[0]和nums[size-1]来作为基准值:以nums[0]为例:

如果比nums[0]大,说明在数组第二象限,left=mid+1(因为不可能在这段区间),反之如果<它,那么可能在第四象限,就需要缩小区间,right=mid,切记不能跳过mid,最后处理边界情况:

如果left一直满足left=mid+1,出循环也就是left==nums.size( ),比如0,1,2,3,4,即left=right的时候

(3)代码
class Solution { public: int findMin(vector<int>& nums) { int left=0,right=nums.size(); while(left<right) { int mid = left+(right-left)/2; if(nums[mid]>=nums[0])left=mid+1; else right=mid; } return left == nums.size() ? nums[0] : nums[left]; } };

Read more

什么是 Session?Web 开发中 Session 的使用与注意事项

什么是 Session?Web 开发中 Session 的使用与注意事项

✅ 引言 在 Web 开发中,HTTP 协议是无状态的,这意味着每次请求之间没有关联。为了实现用户登录、购物车、权限控制等功能,服务器需要一种机制来“记住”用户。Session(会话) 就是解决这一问题的核心技术之一。 本文将深入讲解: * 什么是 Session? * Session 的工作原理 * 在 Java Web 和 Spring Boot 中如何使用 Session * 使用 Session 的最佳实践与常见注意事项 * 安全风险与应对策略 并提供完整的 Java + Spring Boot 示例代码,帮助你全面掌握 Session 的使用。 📌 一、什么是 Session? 1.1 基本定义 Session(会话)是服务器端用于保存用户状态的一种机制。

By Ne0inhk
下载安装Microsoft Edge Webview2教程

下载安装Microsoft Edge Webview2教程

视频教程 Windows 10/11系统 Webview2安装——win10/11 Windows 7系统 Webview2安装——Win7 图文教程 官网下载最新版Webview2安装包 点击下载安装 官网地址:Microsoft Edge WebView2 | Microsoft Edge Developer 1. 进入官网,点击下载按钮 2. 点击左侧常青引导程序下载按钮 3. 在弹出的页面点击接受并下载,右上角下载管理页面在下载完成后有文件弹出 4. 在游览器下载管理页面直接点击打开文件进行软件的安装 5. 软件安装中,安装完成后无需手动点击自动弹出消失。 graph TD A[安装码尚云标签] --> B{判断安装情况} B -->|Yes| C[打开软件进行标签设计] B --&

By Ne0inhk
cpolar远程辅助Open-Lovable实现随时随地克隆网页超实用

cpolar远程辅助Open-Lovable实现随时随地克隆网页超实用

Open-Lovable 是一款面向前端开发者的开源工具,核心功能是将任意网页克隆为可编辑的 React 应用,还支持多类 AI 模型辅助生成代码,适配新手学习、中小企业原型开发等场景。它的优点很贴合实际需求:拆分代码组件清晰,保留完整 CSS 样式,能大幅减少手动搭建页面框架的时间,比如新手学习电商网站布局时,不用再逐行拆解复杂的源代码,直接克隆后就能看清 header、footer 等组件的逻辑,中小企业做产品原型时,克隆同类网页后稍作修改就能快速出效果。 使用这款工具时也有一些实用的小提醒💡:克隆的网页仅能还原静态布局和样式,像登录态、动态交互这类内容无法完整复刻,而且使用前需要准备好 E2B、Firecrawl 等平台的 API 密钥,密钥保管要注意隐私,避免外泄造成不必要的损失。 不过 Open-Lovable 默认只能在本地局域网内使用,这会带来不少不便:比如开发者在家调试的克隆项目,想让公司的设计师远程查看效果,只能通过传文件、远程协助的方式,不仅耗时,还可能出现版本不一致的问题;要是出差在外需要修改克隆的代码,没法直接访问本地的工具,只能等回到电脑前操作,耽误工作

By Ne0inhk
他到底喜欢我吗?赛博塔罗Java+前端实现,一键解答!

他到底喜欢我吗?赛博塔罗Java+前端实现,一键解答!

个人主页-爱因斯晨 文章专栏-赛博算命 原来我们在已往的赛博算命系列文章中的源码已经传到我的Github仓库中,有兴趣的家人们可以自己运行查看。 Github 源码中的一些不足,还恳请业界大佬们批评指正! 本文章的源码已经打包至资源绑定,仓库中也同步更新。 一、引言 在数字化浪潮席卷全球的当下,传统塔罗牌占卜这一古老智慧也迎来了新的表达形式 ——“赛博塔罗”。本文档旨在深入剖析塔罗牌的核心原理,并详细介绍如何利用 Java 语言实现一个简易的塔罗牌预测程序,展现传统神秘学与现代编程技术的融合。 二、塔罗牌原理 (一)集体潜意识与原型理论 瑞士心理学家卡尔・荣格提出的 “集体潜意识” 理论,为塔罗牌的运作提供了重要的心理学支撑。该理论认为,人类拥有超越个体经验的共同心理结构,其中蕴含着 “原型”—— 即普遍存在的、象征性的模式或形象。 塔罗牌的 22 张大阿尔卡那牌恰好与这些基本原型相对应。例如,“愚人” 代表着天真与新开始的原型,“魔术师” 象征着创造力与潜能的原型,“女祭司” 则体现了智慧与直觉的原型。这些原型是全人类共通的心理元素,这也正是不同文化背景的人都能

By Ne0inhk