音乐
暂未播放
LeetCode | 搜索旋转排序数组
分类:二分查找 / 数组
题目#
整数数组 nums 按升序排列,数组中的值互不相同。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= 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:
1输入:nums = [4,5,6,7,0,1,2], target = 02输出:4示例 2:
1输入:nums = [4,5,6,7,0,1,2], target = 32输出:-1讲解#
这题和普通二分查找很像,但是数组被旋转过,整体不再完全升序。
关键点是:虽然整体不是升序,但每次看 left、mid、right 时,左右两半里面一定至少有一半是升序的。
如果 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)
- 时间复杂度:
代码#
源码#
1from typing import List2
3
4class Solution:5 def search(self, nums: List[int], target: int) -> int:6 left = 07 right = len(nums) - 18
9 while left <= right:10 mid = (left + right) // 211 if nums[mid] == target:12 return mid13
14 if nums[left] <= nums[mid]:15 if nums[left] <= target < nums[mid]:16 right = mid - 117 else:18 left = mid + 119 else:20 if nums[mid] < target <= nums[right]:21 left = mid + 122 else:23 right = mid - 124
25 return -1测试#
1from src.python._033_Search_in_Rotated_Sorted_Array import Solution2
3
4sol = Solution()5
6assert sol.search([4, 5, 6, 7, 0, 1, 2], 0) == 47assert sol.search([4, 5, 6, 7, 0, 1, 2], 3) == -18assert sol.search([1], 0) == -19assert sol.search([1], 1) == 010
11print("PASS")参考资料#
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分内容可能已过时
评论区
分享你的想法,与大家交流讨论
音乐
暂未播放



