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] 的大小关系,快速判断哪一侧区间有序;
  • 优化后代码通过三目运算符简化分支,逻辑更紧凑,同时保持原算法的正确性与时间复杂度。
相关推荐
RainCity1 小时前
Java Swing 自定义组件库分享(十三)
java·笔记·后端
QiLinkOS2 小时前
第三视觉理解徐玉生与他的商业活动(28)
大数据·c++·人工智能·算法·开源协议
wabs6662 小时前
关于动态规划【力扣1143.最长公共子序列的思考】
算法·leetcode·动态规划
剑挑星河月2 小时前
54.螺旋矩阵
java·算法·leetcode·矩阵
Robot_Nav3 小时前
MPPI 局部规划器实验设计讲解
人工智能·算法·mppi
mingo_敏3 小时前
Mean-Teacher 均值教师自训练框架详解
算法·均值算法
llllliznc4 小时前
LLM 学习笔记 Day 5:Agent 核心组件——Planner、Memory 与 Reflection
笔记·学习
星空露珠4 小时前
迷你世界UGc3.0脚本Wiki[剧情动画模块管理接口 Timeline]
开发语言·数据结构·算法·游戏·lua
笨笨没好名字4 小时前
Leetcode刷题python3版第一周(下)
linux·算法·leetcode
risc1234564 小时前
“解决了什么痛点”与“为什么有这个东西”的关系?
笔记