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

旋转升序数组上的二分搜索:为何“哪边有序“成为关键决策

这题的本质还是二分搜索,只是先用"哪一半有序"来锁定一个可信的有序区间,然后在这个区间里用普通二分的逻辑排除另一半。整套思路同时适用于普通升序数组和旋转升序数组,可以当成一个更通用的二分模板来记。algo+1​

题目与现象:为什么"整体不升序"还能二分?

题目给的是一个原本严格升序的数组,整体向左旋转了一段,比如:

  • 原数组:[0,1,2,4,5,6,7]
  • 旋转后:[4,5,6,7,0,1,2]

旋转之后,有两条重要性质:notes.suhaib+1​

  1. 数组被切成"前后两段各自升序"的形状,只在某一个位置出现"从大跳到小"的转折点。
  2. 不管在数组哪里取一个 mid,把当前区间 [left, right] 切成两半,总有一半是完全升序的连续区间

这就是整个解法的支点:虽然整体不升序,但"每一步里,总有一半是升序的",在这半边上就可以像普通二分那样思考。algo+1​

关键洞见:如何判断"哪一半有序"?

假设当前在区间 [left, right] 上二分,取中点 mid。想判断左半 [left, mid] 是否有序:notes.suhaib+1​

  • 如果左半里存在旋转点,即存在那次"从大跳小"的地方,那么一定有nums[left] > nums[mid]
    • 直觉上:left 还在"尾部大段",mid 已经绕到"头部小段",所以左端值比中点值大。
  • 反过来说,如果观测到nums[left] <= nums[mid],就说明在 [left, mid] 这一段里没有那次"从大跳小",也就没有旋转点,这整段只能是原数组中的某一段连续片段,因此是严格升序的。

结论就是那句经典判定:stackoverflow+2​

  • nums[left] <= nums[mid]:左半 [left, mid] 有序;
  • 否则右半 [mid, right] 有序(因为整个结构最多只有一个转折点,且两边至少有一边是连续升序)。

这一条,就是"改造版二分"的额外成本,而在普通有序数组里,这个判定永远是"左、右两边都升序",于是是冗余信息。

用"有序的一半"排除另一半:不用管跳跃点

一旦知道哪一半是连续升序,就可以像普通二分一样,做区间判断:algo+1​

如果左半有序nums[left] <= nums[mid]):

  • 如果nums[left] <= target < nums[mid],说明 target 一定在左半 [left, mid-1],于是收缩右端:right = mid - 1
  • 否则,target 不可能在这段升序区间里,只能在右半,收缩左端:left = mid + 1

如果右半有序nums[mid] <= nums[right]):

  • 如果nums[mid] < target <= nums[right],说明 target 一定在右半 [mid+1, right],于是left = mid + 1
  • 否则,target 只能在左半,right = mid - 1

整个过程中,完全不需要显式"找跳跃点":designgurus+1​

  • 若跳跃点在被丢掉的那一半里,直接连同那一半一起被扔掉;
  • 若跳跃点在保留下来的这一半里,下一轮再继续"哪边有序 + 用有序边排除另一边",区间会越来越小,直到跳跃点的存在不再影响"哪边有序"的判断。

可以把"跳跃点"当成一个被动角色:它只是跟着被划分的区间一起被缩小或丢弃,从头到尾都不需要专门处理。

和普通二分有什么本质区别?

从"决策依据"的角度看,两者的核心差异是:geeksforgeeks+2​

普通二分(整体升序):

  • 强前提:对任意 mid,左侧所有元素 < nums[mid],右侧所有元素 > nums[mid]。
  • 决策只要看
    • target < nums[mid]⇒ 去左边;
    • target > nums[mid]⇒ 去右边。
  • 不需要看 nums[left] / nums[right],因为"整体单调"已经隐含"左边都小,右边都大"。

旋转数组上的二分:

  • 整体不单调,左半和右半都可能混有大值和小值。
  • 若只看 target vs nums[mid],会有很多例子把真正答案那半边排除掉。
  • 因此必须先做一步:
    • 用 nums[left] / nums[mid] / nums[right] 判断哪一半是**"当前这一步中,仍然是连续升序"的那一边**;
    • 然后只在这半边里,用普通二分的区间逻辑判断 target 在不在这段,从而决定缩小到哪一边。airtribe+1​

于是,你可以把本题常用写法视为一个更通用的二分模板:

  1. “先定位有序半边”——保证要用它做判断的一整段是单调升序的。
  2. “再在这段里用普通二分逻辑排除另一半”

在普通升序数组上,这套模板也成立,只是"哪边有序"的判断永远得出"两边都有序",于是那部分变成冗余;在旋转数组上,则是必需的。notes.suhaib+1​

官方推荐方案与替代方案

LeetCode 官方题解以及主流教程,推荐的就是上面这套"一次改造版二分":在一个 while 循环里完成"判断哪边有序 + 区间排除",时间复杂度 O(log⁡n),空间 O(1)。leetcode+2​

另一个等价的经典方案是"先找旋转点,再做普通二分":geeksforgeeks+1​

  1. 先用二分找到最小值下标(旋转点),把数组逻辑上分成两段升序。
  2. 再根据 target 与 nums[0] 的大小,决定在前段还是后段上做普通二分。

这两种方法复杂度一样,本质上利用的是同一个性质:

"升序数组经过一次整体旋转后,依然有一半是连续升序,可以当作普通有序区间来二分。"algo+1​

如果你想写一篇自己的博客,可以直接用这四个板块组织结构:

  1. 旋转数组的形状与"唯一一次掉下去"的性质;
  2. 为何 nums[left] <= nums[mid] ⇒ 左半有序;
  3. 在有序半边上如何像普通二分一样排除另一半;
  4. 这套逻辑如何同时覆盖"普通二分"和"旋转二分",成为一个通用模板。
http://www.jsqmd.com/news/98516/

相关文章:

  • 【赵渝强老师】OceanBase中的租户
  • GPT-SoVITS安装包离线部署企业级语音系统的方案
  • AI能源效率危机:大模型能耗远超人类大脑,如何实现可持续发展?
  • 12、用户系统设置全攻略
  • LangFlow在电商商品描述生成中的实际应用
  • 基于微信小程序的农事管理系统设计(源码+lw+部署文档+讲解等)
  • KubePi:让Kubernetes集群管理变得简单直观的现代化面板
  • 从Git Commit到TensorRT镜像构建:全流程技术拆解
  • 2025年义乌美国双清包税国际物流服务推荐榜 - 呼呼拉呼
  • SGMICRO圣邦微 SGM2006-3.0XN5/TR SOT23-5 线性稳压器(LDO)
  • Qwen3-14B-Base:148亿参数如何重塑大模型效率
  • 使用Miniconda高效管理Python环境
  • 机器视觉工控一体机厂商
  • 13、系统设置全解析:从用户到管理员的全方位指南
  • 2025年六偏磷酸钠订做厂家权威推荐榜单:磷酸三钠‌/磷酸二氢钾‌/三聚磷酸钠源头厂家精选 - 品牌推荐官
  • Excalidraw日志收集方案:ELK栈整合实例
  • 2025 年 ROHS 分析仪厂家权威推荐榜:精准检测与高效合规的行业首选仪器 - 品牌企业推荐师(官方)
  • 基于Java+SpringBoot的企业进销存管理系统(源码+lw+部署文档+讲解等)
  • Directus开源数据引擎:打破传统CMS桎梏的企业级解决方案
  • 深入解析:攻防世界—lottery
  • Dify智能体平台调用GPT-SoVITS实现语音播报通知
  • 2025年评价高的不锈钢餐边柜/不锈钢衣柜最新TOP品牌厂家排行 - 品牌宣传支持者
  • 基于清华镜像的TensorFlow开发环境搭建全流程解析
  • 单片机/嵌入式修行之路 - 指南
  • 元推理框架,万法扁鹊问诊系统
  • Qwen3-14B支持哪些GPU?显存需求全解析
  • 2025年靠谱的型钢在线跟切锯切专机/铝板锯切专机用户好评厂家排行 - 品牌宣传支持者
  • Multi-Agent全面爆发!一文详解多智能体核心架构及LangGraph框架
  • GEO重大误区之六:中小企业买不起GEO
  • 制造业设备工厂如何实现8-10个SolidWorks三维设计人员共享一台高性能图形工作站