假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
————————————————
解题思路:
(1)首先用二分查找,找到数组中最小值的索引位置。
(2)找到最小值的索引位置之后,通过二分查找找到相同值所在的位置。
其Python代码如下:
class Solution:
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
def find_rotate_index(left, right): # 找到最小值所在的位置
if nums[left] < nums[right]: # 如果begin值小于end值,则数组是有序的,直接返回0,也就是开始值是最小值
return 0
while left <= right: # 通过二分查找,找到中间值
pivot = (left + right) // 2
if nums[pivot] > nums[pivot + 1]: # 如果中间值的下一个值小于中间值,则最小值为中间值的下一个值
return pivot + 1
else:
if nums[pivot] < nums[left]: # 如果中间值小于开始值,则最小值在左边
right = pivot - 1
else:
left = pivot + 1
def search(left, right): # 寻找是否有匹配的值
"""
Binary search
"""
while left <= right:
pivot = (left + right) // 2
if nums[pivot] == target: # 如果值相同,则返回索引位置
return pivot
else:
if target < nums[pivot]: # 如果target值大于中值,则取中值之前的部分
right = pivot - 1
else: # 如果target值小于中值,则取中值之后的部分
left = pivot + 1
return -1
n = len(nums) # 计算数组长度
if n == 0: # 如果数组为空,则返回-1
return -1
if n == 1: # 如果数组长度为1,则判断值是否等于target
return 0 if nums[0] == target else -1
rotate_index = find_rotate_index(0, n - 1) # 找到最小值所在的位置
# if target is the smallest element
if nums[rotate_index] == target: # 如果最小值的位置等于target
return rotate_index
# if array is not rotated, search in the entire array
if rotate_index == 0: # 如果最小值的索引是0,则搜索整个数组
return search(0, n - 1)
if target < nums[0]: # 如果target值小于索引为0的值,则遍历较小的数组段
# search on the right side
return search(rotate_index, n - 1)
# search on the left side
return search(0, rotate_index) # 如果target大于索引为零的值,则遍历较大的数组段