LeetCode 每日一题笔记 日期:2026.05.22 题目:33. 搜索旋转排序数组

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.05.22
  • 题目:33. 搜索旋转排序数组
  • 难度:中等
  • 标签:数组、二分查找

1. 题目理解

问题描述

给定一个升序数组,在未知下标 k 处左旋后,得到数组 nums(所有值互不相同)。给定目标值 target,返回它在数组中的下标,不存在则返回 -1。要求时间复杂度为 O(log⁡n)O(\log n)O(logn)。

示例

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

输出:4

解释:目标值 0 位于下标4。
输入:nums = [4,5,6,7,0,1,2], target = 3

输出:-1

解释:目标值不存在于数组中。

2. 解题思路

核心观察

  • 旋转后的数组仍保持局部有序 :被 mid 分成的两个区间中,必有一个是完全有序的;
  • 利用二分查找,先判断 mid 所在的区间是否有序,再根据 target 与有序区间的边界关系,决定下一步的搜索方向。

算法步骤

  1. 初始化左右指针 left = 0right = nums.length - 1
  2. 循环直到 left > right
    • 计算 mid = left + (right - left) / 2
    • nums[mid] == target,直接返回 mid
    • 判断左半区是否有序(nums[mid] >= nums[left]):
      • target 在左半区范围内,收缩右边界;
      • 否则收缩左边界;
    • 若右半区有序:
      • target 在右半区范围内,收缩左边界;
      • 否则收缩右边界;
  3. 循环结束未找到,返回 -1

3. 代码实现

java 复制代码
package lc33;

public class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;

        while (left <= right) {
            int mid = left + (right - left) / 2;

            if (nums[mid] == target) {
                return mid;
            }

            // 左半区有序
            if (nums[mid] >= nums[left]) {
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            // 右半区有序
            else {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

4. 代码优化说明

减少冗余判断,通过逻辑等价简化分支,保持可读性的同时压缩代码:

java 复制代码
package lc33;

public class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) return mid;
            if (nums[mid] >= nums[left]) {
                left = (target >= nums[left] && target < nums[mid]) ? left : mid + 1;
                right = (target >= nums[left] && target < nums[mid]) ? mid - 1 : right;
            } else {
                left = (target > nums[mid] && target <= nums[right]) ? mid + 1 : left;
                right = (target > nums[mid] && target <= nums[right]) ? right : mid - 1;
            }
        }
        return -1;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(log⁡n)O(\log n)O(logn)

    二分查找每次将区间减半,最坏情况下执行 log⁡2n\log_2 nlog2n 次循环。

  • 空间复杂度 :O(1)O(1)O(1)

    仅使用常数级额外变量,无递归栈或额外数组开销。

6. 总结

  • 核心思路:局部有序的二分查找,利用旋转数组的特性,每次只在有序区间内判断目标值位置;
  • 关键技巧:通过 nums[mid]nums[left] 的大小关系,快速判断哪一侧区间有序;
  • 优化后代码通过三目运算符简化分支,逻辑更紧凑,同时保持原算法的正确性与时间复杂度。
相关推荐
半夏微凉半夏殇1 小时前
x11与weston对比,优先选哪个
leetcode·均值算法·eclipse
2501_906565121 小时前
数学之美探究
算法
oier_Asad.Chen1 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
青山是哪个青山1 小时前
LangChain 学习笔记(三):LangSmith 调试与监控
笔记·学习·langchain
leisoo80973 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
蒸蒸yyyyzwd3 小时前
cpp选手备战后端学习笔记day6 秋招笔试题
笔记·学习
luj_17685 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
DeviceHub5 小时前
硬件工程师选型笔记:ALPS SKPMAPE010 与 Tonevee TS-3025 贴片轻触开关 PIN TO PIN 评估指南
笔记
郝学胜-神的一滴6 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆6 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill