LeetCode 33:搜索旋转排序数组——Java 两阶段二分查找详解
一、题目描述给定一个元素互不相同、原本按升序排列的整数数组nums。数组在传入函数前可能在某个未知下标处发生了旋转。例如原数组[0,1,2,4,5,6,7]在下标3处旋转后可能变成[4,5,6,7,0,1,2]再给定一个目标值target如果它存在于数组中则返回对应下标否则返回-1。题目要求时间复杂度为O(log n)。普通升序数组可以直接二分查找但旋转后的数组不再整体有序因此不能直接套用标准模板。截图中的解决方案分为两步先找到最小值下标将数组划分成两个升序区间再确定目标值属于哪一段并执行普通二分查找。二、旋转数组的结构观察数组[4,5,6,7,0,1,2]虽然它整体不是升序但可以按照最小值0的位置拆成两段[4,5,6,7] [0,1,2]这两个子区间内部都保持升序。因此只要先找到最小值所在下标minIndex就能得到两个可进行二分查找的区间[0, minIndex - 1] [minIndex, nums.length - 1]所以本题可以拆成两个熟悉的问题二分查找旋转数组中的最小值在确定的升序区间中二分查找target。三、第一步找到最小值下标使用left和right表示当前搜索范围每次取中间位置mid并将nums[mid]与nums[right]比较。1.nums[mid] nums[right]if (nums[mid] nums[right]) { left mid 1; }这说明mid位于旋转点左侧的较大升序段中最小值必然在mid的右边因此可以排除[left,mid]。例如[4,5,6,7,0,1,2] ↑ ↑ mid right此时7 2最小值一定在右半部分。2.nums[mid] nums[right]else if (nums[mid] nums[right]) { right mid; }这说明mid位于包含最小值的右侧升序段中最小值可能正是nums[mid]也可能在它左边所以不能排除mid应令right mid。3.nums[mid] nums[right]else { right--; }本题已说明数组元素互不相同因此正常情况下不会进入这个分支。截图保留right--可以兼容数组存在重复元素的扩展场景相等时无法判断最小值在哪一侧只排除最右侧的一个重复元素。循环条件使用while (left right)当left right时搜索范围中只剩一个位置该位置就是最小值下标。四、第二步判断目标值属于哪一段找到minIndex后旋转数组已经被划分成两个升序区间。接下来需要判断target应该在哪一段查找。令int right nums.length - 1;由于nums[right]是第二个升序区间的最大值可以将target与它比较。1.nums[right] target目标值大于第二段中的最大值所以不可能在第二段只能在第一段return searchBinary(nums, target, 0, minIndex - 1);2.nums[right] target结合题目的旋转结构目标值若存在应在以最小值开头的第二段中查找return searchBinary(nums, target, minIndex, right);如果target比数组最小值还小虽然也会进入第二段搜索但普通二分最终会返回-1。3.nums[right] target最后一个元素正好就是目标值可以直接返回return right;这种判断方式避免了额外比较nums[0]并与截图中的实现保持一致。五、第三步在升序区间中二分查找确定目标区间后剩下的就是标准二分查找。本文使用闭区间[left,right]所以循环条件为while (left right)如果中间元素小于目标值搜索右侧如果中间元素大于目标值搜索左侧如果相等直接返回mid。if (nums[mid] target) { left mid 1; } else if (nums[mid] target) { right mid - 1; } else { return mid; }区间耗尽仍未命中说明目标值不存在返回-1。六、完整 Java 代码下面的代码严格采用截图中的“先找最小值再选择区间最后普通二分”的结构class Solution { public int search(int[] nums, int target) { // 找到最小值下标从而划分出两个升序区间 int minIndex findMin(nums); int right nums.length - 1; // target 大于第二段最大值只可能位于第一段 if (nums[right] target) { return searchBinary(nums, target, 0, minIndex - 1); } else if (nums[right] target) { // target 若存在应位于第二段 return searchBinary(nums, target, minIndex, right); } // nums[right] target return right; } // 在指定闭区间中执行标准二分查找 private int searchBinary(int[] nums, int target, int left, int right) { while (left right) { int mid left ((right - left) 1); if (nums[mid] target) { left mid 1; } else if (nums[mid] target) { right mid - 1; } else { return mid; } } return -1; } // 查找旋转数组中最小值所在的下标 private int findMin(int[] nums) { int left 0; int right nums.length - 1; while (left right) { int mid left ((right - left) 1); if (nums[mid] nums[right]) { // mid 位于左侧较大升序段 left mid 1; } else if (nums[mid] nums[right]) { // mid 位于包含最小值的升序段 right mid; } else { // 本题元素不重复该分支用于兼容重复元素 right--; } } return left; } }七、复杂度分析findMin使用二分查找定位最小值时间复杂度为O(log n)searchBinary又执行一次二分查找时间复杂度也是O(log n)。两者顺序执行O(log n) O(log n) O(log n)算法只使用常数个变量因此空间复杂度为O(1)。需要注意如果扩展到存在大量重复元素的数组right--可能使findMin在最坏情况下退化为O(n)但本题元素互不相同不存在该问题。八、常见错误1. 找最小值时写成right mid - 1当nums[mid] nums[right]时mid本身可能就是最小值所以必须保留它写成right mid。2. 使用错误的循环条件findMin的目标是让两个指针相遇应使用left right普通二分使用闭区间需要使用left right。3. 第一段的右边界写成minIndex最小值属于第二段第一段应为[0,minIndex - 1]。否则两个区间会发生重叠。4. 忘记处理未旋转数组例如[1,2,3,4]的最小值下标是0。此时第一段为[0,-1]是空区间若目标值大于nums[right]的情况不会出现其余目标会进入第二段[0,right]代码仍能正确运行。九、总结搜索旋转排序数组的关键是认识到旋转只破坏了整体有序性却保留了两个局部升序区间。本解法先通过findMin定位最小值下标将数组划分为两段再比较target与最后一个元素选择可能包含目标值的升序区间最后使用标准二分查找得到答案。

相关新闻

drawsvg性能优化:提升SVG生成与渲染效率的7个实用技巧

drawsvg性能优化:提升SVG生成与渲染效率的7个实用技巧

drawsvg性能优化:提升SVG生成与渲染效率的7个实用技巧 【免费下载链接】drawsvg Moving to https://tangled.org/cduck.me/drawsvg/ Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets 项目地址: https://gitcode.com…

2026/10/1 11:32:35 阅读更多 →
深度解析Qwen3-VL-8B-Instruct-w4a16-llmcompressor-v0.12.0量化技术:W4A16如何平衡性能与精度

深度解析Qwen3-VL-8B-Instruct-w4a16-llmcompressor-v0.12.0量化技术:W4A16如何平衡性能与精度

深度解析Qwen3-VL-8B-Instruct-w4a16-llmcompressor-v0.12.0量化技术:W4A16如何平衡性能与精度 【免费下载链接】Qwen3-VL-8B-Instruct-w4a16-llmcompressor-v0.12.0 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Qwen3-VL-8B-Instruct-w4a16-llmcompressor…

2026/10/1 15:16:21 阅读更多 →
新手必看:R3PLAYX界面导航与基础操作完全指南

新手必看:R3PLAYX界面导航与基础操作完全指南

新手必看:R3PLAYX界面导航与基础操作完全指南 【免费下载链接】music a music player forked from YesPlayMusic。高颜值的第三方网易云播放器,支持 Windows / macOS / Linux :electron/Docker: 项目地址: https://gitcode.com/gh_mirrors/music/music…

2026/9/12 2:59:13 阅读更多 →

最新新闻

DeepSeek Harness客户端详解:Token管理与多模型接入实战

DeepSeek Harness客户端详解:Token管理与多模型接入实战

DeepSeek Harness 客户端开放下载,消息一出,不少做 AI 应用开发的朋友都在群里聊这件事。如果你平时经常调 DeepSeek 的 API,或者需要在本地同时管理多个主流大模型的对话与调用,这个客户端确实值得花几分钟试一下。它把模型接入、…

2026/10/2 22:53:09 阅读更多 →
职工考勤管理系统:从数据库设计到状态判定完整实战

职工考勤管理系统:从数据库设计到状态判定完整实战

简介:数据库课程设计——职工考勤管理信息系统完整设计文档,面向计算机相关专业学生及需要完成数据库课程设计的人员。文档以企业考勤管理为背景,系统阐述从需求分析、概念结构设计到逻辑结构设计、物理结构设计与数据库实施的完整流程&#…

2026/10/2 22:53:09 阅读更多 →
互联网商业医疗保险直付平台:从理赔垫付到秒级结算的落地拆解

互联网商业医疗保险直付平台:从理赔垫付到秒级结算的落地拆解

简介:这份PDF文献面向医疗信息化从业者、医院信息中心技术人员及医疗保障研究者,聚焦互联网商业医疗保险直付平台的解决方案。内容系统梳理了商保的概况与现状、传统理赔流程的痛点,并重点论述平台设计原则,包括数据安全、实时性、…

2026/10/2 22:52:08 阅读更多 →
PPTX作为云架构契约:从幻灯片到可执行基础设施

PPTX作为云架构契约:从幻灯片到可执行基础设施

简介:本资源是一份面向智慧城市、大数据与人工智能领域技术决策者及系统架构师的《高效数据中心云基础架构解决方案》专业PPT课件,聚焦企业级IT基础设施向云化演进的核心路径。内容系统阐述动态基础架构管理(AIM)、基础架构云&…

2026/10/2 22:52:08 阅读更多 →
Jev AI研发智能体:任务闭环、本地部署与Codex集成实践

Jev AI研发智能体:任务闭环、本地部署与Codex集成实践

最近社区里聊 Jev 的人越来越多了,但大部分人还停留在"听说它很厉害"的阶段。有人说它是新的 AI 模型,有人说它就是个编码插件,还有人拿它和 Codex 对比,问是不是要抢饭碗。我前阵子也花了不少时间研究 Jev,…

2026/10/2 22:52:08 阅读更多 →
RAGFlow深度解析:企业知识库文档解析与本地部署实战

RAGFlow深度解析:企业知识库文档解析与本地部署实战

1. 先从“文档抽血”说起:RAGFlow 到底解决了什么 企业知识库这条赛道上,开源方案看着一堆,真能拿来当生产力的没几个。RAGFlow 是其中一个让我愿意花时间反复测试的项目。它最打动我的地方,不是又出了一款“聊天问答机器人”&…

2026/10/2 22:52:08 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →