news 2026/9/28 4:51:19

【二分查找-1】33.搜索旋转排序数组

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【二分查找-1】33.搜索旋转排序数组

题目描述:

整数数组nums按升序排列,数组中的值互不相同。

在传递给函数之前,nums在预先未知的某个下标k(0 <= k < nums.length)上进行了向左旋转,使数组变为[nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标从 0 开始计数)。例如,[0,1,2,4,5,6,7]下标3上向左旋转后可能变为[4,5,6,7,0,1,2]。

给你旋转后的数组nums和一个整数target,如果nums中存在这个目标值target,则返回它的下标,否则返回-1。

你必须设计一个时间复杂度为O(log n)的算法解决此问题。

示例 1:

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

示例 2:

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

示例 3:

输入:nums = [1], target = 0输出:-1

解题思路:

方法:二分查找

核心思路:

旋转后的数组,从中间切开,至少有一半是有序的:

[4, 5, 6, 7, 0, 1, 2] ↑ mid=3 左半部分 [4, 5, 6, 7] 有序 右半部分 [0, 1, 2] 有序

判断哪一半有序,然后看 target 是否在有序的那一半中。

算法步骤:

  1. 计算mid

  2. 如果nums[mid] == target,返回mid

  3. 判断左半部分是否有序:nums[left] <= nums[mid]

    • 如果左半部分有序:

      • 如果nums[left] <= target < nums[mid],在左半部分找 →right = mid - 1

      • 否则在右半部分找 →left = mid + 1

    • 如果右半部分有序:

      • 如果nums[mid] < target <= nums[right],在右半部分找 →left = mid + 1

      • 否则在左半部分找 →right = mid - 1

具体过程示例:

nums = [4, 5, 6, 7, 0, 1, 2],target = 0

初始: left=0, right=6, mid=3 [4, 5, 6, 7, 0, 1, 2] ↑ ↑ ↑ left mid right nums[mid]=7 != 0 nums[left]=4 <= nums[mid]=7 → 左半部分有序 target=0 不在 [4, 7) 中 → 在右半部分找 left = mid+1 = 4 left=4, right=6, mid=5 [4, 5, 6, 7, 0, 1, 2] ↑ ↑ ↑ left mid right nums[mid]=1 != 0 nums[left]=0 <= nums[mid]=1 → 左半部分有序 target=0 在 [0, 1) 中 → 在左半部分找 right = mid-1 = 4 left=4, right=4, mid=4 nums[mid]=0 == target → 返回 4 ✅

代码实现:

class Solution { public: int search(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return mid; } // 判断左半部分是否有序 if (nums[left] <= nums[mid]) { // 左半部分有序 if (nums[left] <= target && target < nums[mid]) { right = mid - 1; // target 在左半部分 } else { left = mid + 1; // target 在右半部分 } } else { // 右半部分有序 if (nums[mid] < target && target <= nums[right]) { left = mid + 1; // target 在右半部分 } else { right = mid - 1; // target 在左半部分 } } } return -1; } };

复杂度分析:

维度复杂度说明
时间复杂度O(log n)每次排除一半
空间复杂度O(1)只用常数个变量

关键细节:

1. 为什么用nums[left] <= nums[mid]判断左半部分有序?
  • 如果nums[left] <= nums[mid],说明左半部分没有旋转点,是有序的

  • 否则,旋转点在左半部分,右半部分有序

2. 为什么用<=而不是<?

因为nums[mid]可能等于nums[left](比如left == mid时),用<=更安全。

3. 边界条件
if (nums[left] <= target && target < nums[mid])
  • target < nums[mid]不是<=,因为nums[mid] == target已经在前面判断过了

  • nums[left] <= target是<=,因为nums[left]可能就是 target

4. 和「搜索旋转排序数组 II」的区别
题目区别
33. 搜索旋转排序数组值互不相同
81. 搜索旋转排序数组 II值可能重复

81 题需要额外处理nums[left] == nums[mid] == nums[right]的情况。

总结:

要点说明
核心思想二分查找,判断哪一半有序
关键判断nums[left] <= nums[mid]判断左半部分有序
时间复杂度O(log n)
空间复杂度O(1)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 4:47:52

从一行语法读懂 SAP HANA SQL 文档

我在核对一段建表语句时,经常会同时打开 SAP HANA 的 SQL 参考文档。真正费时间的,有时不是理解 CREATE TABLE 的业务用途,而是读懂语法栏里密集的尖括号、方括号、花括号和省略号。同样一个逗号,写在语法公式里可能表示实际要输入的分隔符;写在说明文字里,则只是标点。倘…

作者头像 李华
网站建设 2026/9/28 4:47:37

SAP HANA 中的临时数据,究竟该放在哪里

一笔采购订单进入审批流程时,系统可能要读取订单行、计算金额、匹配审批规则,再把候选审批人交给下一步处理。这些中间结果并不都值得写入正式业务表。有些只在一次计算中出现,有些需要在同一数据库会话的几次操作之间保留,还有些数据虽然只是临时数据,却必须使用一张预先…

作者头像 李华
网站建设 2026/9/28 4:46:23

STM32标准外设库、HAL库实现流水灯

本次实验继续使用 STM32F103C8T6 最小系统板和三个外接 LED。在任务二中&#xff0c;我使用 STM32 标准外设库实现流水灯&#xff1b;在任务三中&#xff0c;我改用 HAL 库&#xff0c;并加入按键中断控制流水灯暂停和恢复。 实验目的 熟悉 STM32 标准外设库和 HAL 库的基本工…

作者头像 李华
网站建设 2026/9/28 4:46:15

DeepSeek LeetCode 122. 买卖股票的最佳时机 II Rust实现

LeetCode 122. 买卖股票的最佳时机 II&#xff08;Rust 实现&#xff09; 思路 由于可以无限次交易&#xff0c;且任意时刻最多持有一股&#xff0c;所以只要后一天价格比前一天高&#xff0c;就可以在前一天买入、后一天卖出&#xff0c;赚取差价。将所有相邻两天的正收益累加…

作者头像 李华
网站建设 2026/9/28 4:46:10

第八章 组网技术

第八章 组网技术 8-1 交换机 交换机分类 ■ 1.根据交换方式分存储转发式交换&#xff08;Store and Forward&#xff09;&#xff1a;完整接收数据帧&#xff0c;缓存、验证、碎片过滤&#xff0c;然后转发。优点&#xff1a;可以提供差错校验和非对称交换。缺点&#xff1a;延…

作者头像 李华
网站建设 2026/9/28 4:46:08

玻尔兹曼机:深度学习的「前世」,从统计力学到 RBM

从统计力学到受限玻尔兹曼机&#xff0c;理解深度学习的历史脉络开头&#xff1a;统计力学和机器学习有什么关系&#xff1f; 上一篇我们学习了信息论&#xff0c;用熵度量不确定性。 今天我们学习玻尔兹曼机——深度学习的「前世」。 统计力学&#xff1a; 研究大量粒子的宏观…

作者头像 李华