假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums:
return -1
index = -1
left, right = 0, len(nums)-1
index = self.binarySearch(nums, target, left, right)
return index
def binarySearch(self, nums, target, left, right):
index = -1
middle = (left+right) >> 1
if nums[middle] == target:
index = middle
return index
if left == right:
return index
#positive order
if nums[left] <= nums[right]:
if target >= nums[left] and target <= nums[middle]:
index = self.binarySearch(nums, target, left, middle-1)
if target >= nums[left] and target >= nums[middle]:
index = self.binarySearch(nums, target, middle+1, right)
#rotated sorted array
else:
if nums[middle] < nums[left]:
if target >= nums[left] or target <= nums[middle]:
index = self.binarySearch(nums, target, left, middle-1)
if target >= nums[middle] and target <= nums[right]:
index = self.binarySearch(nums, target, middle+1, right)
else:
if target >= nums[left] and target <= nums[middle]:
index = self.binarySearch(nums, target, left, middle-1)
if target >= nums[middle] or target <= nums[right]:
index = self.binarySearch(nums, target, middle+1, right)
return index
由于数组是排列之后再进行旋转的,所以数组具有局部的有序性。利用这个特性我们可以使用二分查找来寻找目标值,但是比较麻烦的一点是需要判断折叠点是在中点的左侧还是中点的右侧,这里需要分类讨论来决定到底是在左边进行查询还是在右边进行进一步的查询。最后一点需要注意的就是对边界值的考虑,当最后子数组变成长度为2时,我们需要检查逻辑是否还成立。
其实这里可以不使用递归,而使用迭代,代码量会少一些。如果使用递归就需要重新构造函数。