LeetCode Hot 100 搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

复制代码
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4

示例 2:

复制代码
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1

示例 3:

复制代码
输入:nums = [1], target = 0
输出:-1

📖 文字题解

方法一:二分查找

思路和算法

对于有序数组,可以使用二分查找的方法查找元素。

但是这道题中,数组本身不是有序的,进行旋转后只保证了数组的局部是有序的,这还能进行二分查找吗?答案是可以的。

可以发现的是,我们将数组从中间分开成左右两部分的时候,一定有一部分的数组是有序的。拿示例来看,我们从 6 这个位置分开以后数组变成了 [4, 5, 6][7, 0, 1, 2] 两个部分,其中左边 [4, 5, 6] 这个部分的数组是有序的,其他也是如此。

这启示我们可以在常规二分查找的时候查看当前 mid 为分割位置分割出来的两个部分 [l, mid][mid + 1, r] 哪个部分是有序的,并根据有序的那个部分确定我们该如何改变二分查找的上下界,因为我们能够根据有序的那部分判断出 target 在不在这个部分:

  • 如果 [l, mid - 1] 是有序数组,且 target 的大小满足 [nums[l],nums[mid]),则我们应该将搜索范围缩小至 [l, mid - 1],否则在 [mid + 1, r] 中寻找。
  • 如果 [mid, r] 是有序数组,且 target 的大小满足 (nums[mid+1],nums[r]],则我们应该将搜索范围缩小至 [mid + 1, r],否则在 [l, mid - 1] 中寻找。

需要注意的是,二分的写法有很多种,所以在判断 target 大小与有序部分的关系的时候可能会出现细节上的差别。

cpp 复制代码
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = (int)nums.size();
        int left = 0, right = n-1;
        if(!n)
        {
            return -1;
        }
        if(n == 1)
        {
            return nums[0] == target ? 0 : -1;
        }
        while(left <= right)
        {
            int mid = (right + left) /2;
            if(nums[mid] == target) return mid;
            if(nums[0] <= nums[mid])
            {
                if(nums[0] <= target && target < nums[mid])
                {
                    right = mid - 1;
                }
                else
                {
                    left = mid + 1;
                }
            }
            else
            {
                if(nums[mid] < target && target <= nums[n - 1])
                {
                    left = mid + 1;
                } 
                else
                {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
};
相关推荐
无极低码1 小时前
ecGlypher新手安装分步指南(标准化流程)
人工智能·算法·自然语言处理·大模型·rag
软件算法开发1 小时前
基于海象优化算法的LSTM网络模型(WOA-LSTM)的一维时间序列预测matlab仿真
算法·matlab·lstm·一维时间序列预测·woa-lstm·海象优化
罗超驿2 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
superior tigre2 小时前
22 括号生成
算法·深度优先
努力也学不会java3 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎3 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan4 小时前
朱梁万有递归元定理,重构《易经》
算法·重构
智者知已应修善业4 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机
khddvbe4 小时前
C++并发编程中的死锁避免
开发语言·c++·算法
C羊驼4 小时前
C语言:两天打鱼,三天晒网
c语言·经验分享·笔记·算法·青少年编程