搜索旋转排序数组

LeetCode 33 题解笔记

Posted by BY on April 26, 2026

原始笔记只贴了一份代码。这里把”旋转数组上的二分”的判定原理写一下,代码保留原样。

题目背景

LeetCode 33「搜索旋转排序数组」。一个原本严格递增的数组被旋转过一次,给一个目标值 target,找出它在数组中的下标,找不到返回 -1。要求 O(log n)

概念解释

  • 半有序性质:旋转数组的任意一次二分,nums[l..mid]nums[mid..h]至少有一段是完全有序的
  • 判定有序的一段:通过比较 nums[mid]nums[l](或 nums[h])即可判断。本笔记同时考虑了 == 的情况,处理”含重复值”的退化分支(实际本题元素唯一,但保留原代码)。

实现原理

每轮根据 mid 与端点的关系,先确定哪一侧有序,再判断 target 是否落在该有序段的值域内:

  • nums[mid] > nums[l],左段 [l, mid] 有序:
    • nums[l] ≤ target < nums[mid] → 收缩到左段 h = mid - 1
    • 否则进入右段 l = mid + 1
  • nums[mid] < nums[h],右段 [mid, h] 有序:
    • nums[mid] < target ≤ nums[h] → 收缩到右段 l = mid + 1
    • 否则进入左段 h = mid - 1
  • nums[mid] == nums[l]== nums[h]:无法判定,做最小步收缩,等价于线性退化的兜底。

任意一步如果 nums[mid] == target,立即返回 mid

时间复杂度 O(log n),最坏(出现等值时)退化为 O(n);空间 O(1)

参考实现

class Solution {
public:
    int search(vector<int>& nums, int target) {


        int l = 0;
        int h = nums.size() - 1;

        while(l <= h)
        //闭区间
        {
            int mid = l + (h - l )/2;
            // std::cout << mid << std::endl;
            if(nums[mid] > nums[l])
            //左侧有序
            {
                if(nums[mid] > target && nums[l] <= target)
                //判断左侧有序范围是否符合要求
                {
                    h = mid - 1;
                }else if(nums[mid] == target)
                {
                    return mid;
                }else
                {
                    l = mid + 1;
                }
            }else if(nums[mid] == nums[l])
            {
                if(nums[mid] == target)
                {
                    return mid;
                }else
                {
                    l = mid +1;
                }
            }else if(nums[mid] < nums[h])
            //右侧有序
            {
                if(nums[mid] < target && target <= nums[h])
                 //判断右侧有序范围是否符合要求
                {
                    l = mid + 1;
                }else if(nums[mid] == target)
                {
                    return mid;
                }else
                {
                    h = mid - 1;
                }
            }else if(nums[mid] == nums[h])
            {
                if(nums[mid] == target)
                {
                    return mid;
                }else
                {
                    h = mid - 1;
                }
            }

        }


        return -1;

    }
};