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] 的大小关系,快速判断哪一侧区间有序;
  • 优化后代码通过三目运算符简化分支,逻辑更紧凑,同时保持原算法的正确性与时间复杂度。
相关推荐
INS_KF4 小时前
【编程笔记】成员函数中两个 const 的区别(const Data &getData() const;)
前端·javascript·笔记
淡海水4 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
leobertlan4 小时前
好玩系列:训练一个神经网络模型指导小孩玩游戏2-大局观教练
算法
Tisfy5 小时前
LeetCode 3876.构造奇偶一致的数组 II:三种情况分类讨论(其实还是脑筋急转弯)
算法·leetcode·题解·脑筋急转弯
tju新生代魔迷5 小时前
Verilog HDL 学习笔记(十三)| 第13章 编程语言接口(PLI)
笔记·学习
乐迪信息6 小时前
智慧港口船舶AI算法实现在线状态监测
大数据·人工智能·深度学习·算法·计算机视觉
点心的游戏开发世界7 小时前
UnityShaderGraph滚动UV笔记
笔记·uv
瑞码空间7 小时前
git知识点黄金笔记
笔记·git·elasticsearch
木井巳7 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
心抵鹊8 小时前
归并排序之翻转对(hard)
数据结构·算法