假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -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
解题思路:时间复杂度要求为logn 二分查找
0 1 2 4 5 7 6
7 0 1 2 4 5 6
6 7 0 1 2 4 5
5 6 7 0 1 2 4
4 5 6 7 0 1 2
2 4 5 6 7 0 1
1 2 4 5 6 7 0
以上为实例的几种旋转情况,细心观察可以发现:当中心点(加粗的位置)大于末位时,中心点左侧是有序,右侧可能有序;
同理,当中心点(加粗的位置)小于末位时,中心点右侧是有序,左侧可能有序。那么如果目标值在有序数列之间则直接调用二分查找;如若不在,则对可能有序的数组重复上述步骤。
代码:
class Solution:
def search(self, nums: List[int], target: int) -> int:
first, last = 0, len(nums)-1
while first <= last:
mid = (first+last) // 2
if nums[mid] == target:
return mid
elif nums[mid] > nums[last]: #左侧有序
if nums[first] <= target <= nums[mid]: #目标值在有序数组内
return self.binary_search(nums, target, first, mid+1)
else: #目标值在无序数组内
first = mid+1
elif nums[mid] < nums[last]: #右侧有序
if nums[mid] <= target <=nums[last]: #目标值在有序数组内
return self.binary_search(nums, target, mid-1, last)
else: #目标值在无序数组内
last =mid
else:
return -1
return -1
def binary_search(self, alist, item, first, last):
while first <= last:
mid = (first+last) // 2
if item < alist[mid]:
last = mid-1
elif item > alist[mid]:
first = mid + 1
else:
return mid
return -1