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] 的大小关系,快速判断哪一侧区间有序;
  • 优化后代码通过三目运算符简化分支,逻辑更紧凑,同时保持原算法的正确性与时间复杂度。
相关推荐
懿路向前17 小时前
【HarmonyOS学习笔记】2026-07-24 | textProcessing 实体识别与踩坑实录
笔记·学习·边缘计算·harmonyos
闪电悠米17 小时前
力扣hot100-54.螺旋矩阵-模拟边界控制详解
算法·leetcode·矩阵
变量未定义~17 小时前
虚拟节点-星石传送阵(4星)、强连通分量
数据结构·算法
春生野草17 小时前
C基础--八大排序(个人笔记)
c语言·笔记·排序算法
IT方大同18 小时前
C语言分支与循环语句
c语言·开发语言·算法
待磨的钝刨18 小时前
深入理解主成分分析(PCA)
人工智能·线性代数·算法·机器学习
caimouse18 小时前
MM 学习笔记 09:进程会话与工作集
笔记·学习·reactos
星恒随风18 小时前
C++ 继承进阶:默认成员函数、多继承、虚继承与组合设计
开发语言·c++·笔记·学习
foo1st19 小时前
MySQL 8.0(Windows)升级笔记
数据库·笔记·mysql
geovindu19 小时前
java: Backtracking Algorithm
java·开发语言·windows·后端·算法·回溯算法