LeetCode | 搜索旋转排序数组

570 字
3 分钟
LeetCode | 搜索旋转排序数组

分类:二分查找 / 数组

题目#

整数数组 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

讲解#

这题和普通二分查找很像,但是数组被旋转过,整体不再完全升序。

关键点是:虽然整体不是升序,但每次看 leftmidright 时,左右两半里面一定至少有一半是升序的。

如果 nums[left] <= nums[mid],说明左半边 [left, mid] 是升序的。此时判断 target 是否落在 nums[left]nums[mid] 之间:如果在,就去左半边找;否则去右半边找。

如果左半边不是升序的,那右半边 [mid, right] 一定是升序的。此时判断 target 是否落在 nums[mid]nums[right] 之间:如果在,就去右半边找;否则去左半边找。

所以这题不是直接比较 nums[mid]target 后决定左右,而是先判断哪一半有序,再判断 target 在不在有序的那一半里。

复杂度#

  • 暴力做法:
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  • 二分查找:
    • 时间复杂度:O(log(n))
    • 空间复杂度:O(1)

代码#

源码#

from typing import List
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
if nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1

测试#

from src.python._033_Search_in_Rotated_Sorted_Array import Solution
sol = Solution()
assert sol.search([4, 5, 6, 7, 0, 1, 2], 0) == 4
assert sol.search([4, 5, 6, 7, 0, 1, 2], 3) == -1
assert sol.search([1], 0) == -1
assert sol.search([1], 1) == 0
print("PASS")

参考资料#

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

LeetCode | 搜索旋转排序数组
https://leetcode.cn/problems/search-in-rotated-sorted-array/
作者
平昊阳
发布于
2026-08-08
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
平昊阳
乘长风,破巨浪, 展鸿图于未央!
--
总访问量
--
访客数
公告
欢迎来到我的个人博客!欢迎关注交流吖!
更多相关公告,见
社交-留言」。
音乐
封面

音乐

暂未播放

0:000:00
暂无歌词
站点统计
文章
66
分类
16
标签
93
总字数
477,284
运行时长
0
最后活动
0 天前

文章目录