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

二分查找经典——力扣153.寻找旋转排序数组中的最小值

力扣153.寻找旋转排序数组中的最小值
在这里插入图片描述


【二分查找经典】寻找旋转排序数组中的最小值 —— 力扣 153题

前言

在面试中,二分查找几乎是“必考题型”。很多人以为二分查找只是用来“找某个数”,但真正的考察往往是:能否灵活运用二分的思想,解决那些稍微变形的场景。

这道题——寻找旋转排序数组中的最小值,就是二分查找的经典应用之一。它看起来只是一个数组最小值问题,但要求时间复杂度必须是 O(log n),这就直接把你推向了二分查找的怀抱。

如果你还停留在套模板的阶段,这道题一定会给你新的启发:二分查找的核心不是“找数”,而是“缩小边界,逐步逼近答案”。


一、题目描述

已知一个长度为 n 的数组,预先按照升序排列,经由 1n旋转 后,得到输入数组。

  • 例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

    • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
    • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]

现在,给你一个元素值 互不相同 的数组 nums,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。

请你找出并返回数组中的 最小元素

要求时间复杂度必须为 O(log n)


示例 1

输入:nums = [3,4,5,1,2]
输出:1

示例 2

输入:nums = [4,5,6,7,0,1,2]
输出:0

示例 3

输入:nums = [11,13,15,17]
输出:11

提示

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 中的所有整数互不相同
  • nums 原来是一个升序数组,并进行了 1n 次旋转

二、题目分析

这道题的关键点:

  1. 原始数组是升序排列的。
  2. 旋转后,数组被拆成了两段有序的部分。
  3. 我们要找到那段断裂处的最小值。
  4. 要求 O(log n),直指 二分查找

直观想法:

  • 如果数组没有被旋转,比如 [1,2,3,4,5],最小值就是 nums[0]
  • 如果数组被旋转,比如 [4,5,6,7,0,1,2],最小值就是右半部分的第一个元素。

那么问题就转化为:
如何用二分定位这个最小值所在的区间?


三、解法探讨

方法一:暴力扫描(O(n))

最简单的想法是直接遍历数组,找到最小值。
代码很简单,但时间复杂度是 O(n),不符合题目要求。


方法二:二分查找(O(log n))【推荐解法】

核心思路:

  1. 初始化左右指针 left = 0, right = nums.length - 1

  2. 每次取中点 mid

    • 如果 nums[mid] > nums[right],说明最小值在 右半部分
    • 否则,最小值在 左半部分或就是 mid
  3. 循环结束时,left == right,即最小值位置。

代码实现
class Solution {public int findMin(int[] nums) {int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > nums[right]) {// 最小值在右半部分left = mid + 1;} else {// 最小值在左半部分(包括 mid)right = mid;}}return nums[left];}
}

方法三:小优化的二分查找

其实我们还能加个小优化:

  • 如果 nums[left] < nums[right],说明数组根本没被旋转,直接返回 nums[left]
代码实现
class Solution {public int findMin(int[] nums) {if (nums[0] < nums[nums.length - 1]) {return nums[0]; // 没有旋转}int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > nums[right]) {left = mid + 1;} else {right = mid;}}return nums[left];}
}

这个小判断能减少一部分计算量,虽然对复杂度没影响,但写起来更优雅。


四、复杂度分析

  • 时间复杂度

    • 方法一:O(n)
    • 方法二/三(二分):O(log n) ✅ 符合要求
  • 空间复杂度

    • O(1),仅使用了常数级变量

五、总结

这道题本质上是 二分查找的边界问题

  • 核心是通过比较 nums[mid]nums[right],判断最小值落在哪一半。
  • 题目要求 O(log n),暴力方法直接淘汰,二分才是正解。
  • 如果你能把这种思路融会贯通,会发现很多旋转数组相关题目其实都是换汤不换药。

面试视角小结:

  • 这题常出现在一线大厂的面试中,考察点就是“能不能在变形场景里用对二分查找”。

  • 常见误区:

    1. 直接遍历,没注意到复杂度要求。
    2. 二分写错边界,死循环。
  • 掌握这题,相当于对二分查找的理解更深了一层。

一句话总结:
旋转数组找最小值,记住用二分锁定断点,一步一步缩小区间,最终就能找到答案。


http://www.dtcms.com/a/394777.html

相关文章:

  • 离散数学之命题逻辑
  • 【Linux命令从入门到精通系列指南】ping 命令详解:网络连通性诊断的终极工具
  • 游戏UI告别“贴图”时代:用Adobe XD构建“活”的设计系统
  • NXP - 用MCUXpresso IDE导入lpcopen_2_10_lpcxpresso_nxp_lpcxpresso_1769.zip中的工程
  • ✅ Python+Django租房推荐系统 双协同过滤+Echarts可视化 租房系统 推荐算法 全栈开发(建议收藏)✅
  • Django入门-3.公共视图
  • 【 设计模式 | 结构型模式 代理模式 】
  • 小杰机器学习高级(five)——分类算法的评估标准
  • IS-IS 中同时收到 L1 和 L2 的 LSP 时,是否优选 L1
  • 【开源】基于STM32的智能车尾灯
  • 电子电气架构 --- 软件开发与产品系统集成流程(下)
  • Ubuntu系统目录架构是怎么样的
  • 自动驾驶仿真之“场景交互”技术研究
  • 《AI管家还是数字化身?—— 一种面向未来的个人智能架构构想》
  • AI提升工业生产制造安全,基于YOLOv9全系列【yolov9/t/s/m/c/e】参数模型开发构建工业生产制造加工场景下工业设备泄漏智能化检测识别预警系统
  • 深度学习(十一):深度神经网络和前向传播
  • js立即执行函数的几种写法
  • RecyclerView里更新列表数是不想让header也刷新,怎么处理
  • C#/.NET/.NET Core技术前沿周刊 | 第 55 期(2025年9.15-9.21)
  • 减少实验烦恼,革新实验效率——PFA塑料容量瓶降低实验成本与风险
  • 留给石头科技的赛道不多了
  • 基于卷积神经网络的人车识别技术:从原理突破到场景重构的深度探索
  • 信用免押租赁服务:重构消费信任体系的全球增长引擎
  • Redis数据迁移实战:从自建到云托管(阿里云/腾讯云)的平滑过渡
  • 从梵高到赛博格:我用4K模型重构艺术史的未来可能性-Seedream 4.0 实测
  • Mysql DBA学习笔记(Redo Log/Undo Log)
  • 买卖T平台如何以分红+排队免单重构零售生态?
  • 2025 年前端工具全景解析:从框架到 AI,重构开发效率的 N 种可能
  • 重构ruoyi前后端分离版
  • AI + 制造:AI 如何重构制造业的质检与排产流程