目录
问题
假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [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
解题思路
分析:这是一道比较迷惑人的题目,注意题干要求:1)“数组中不存在重复的元素”;2)“时间复杂度必须是 O(log n) 级别”。
第二点要求,基本就明确了,要达到要求,就只有用二分查找了。而第一点要求就是要实现第二点要求的既定前提。
题目中隐含两个道理:1)从任何一个位置一分为二后,必然有一边是有序的,一边是无序的,并且无序的继续同样的操作,结论依然成立;2)对于升序排序的数组在预先未知的某个点上进行了旋转后的数组(不存在重复元素),如果数组的中位数大于数组的第一个值,则左边是有序的;否则,右边是有序的(这是对第一点的进一步理解分析结果)。
无论是左边有序还是右边有序,都可以容易判断出target是在左半部分还是右半部分,并且继续同样的判断操作,因此,解题方法用递归操作,简单易行。具体参考下文代码:
python具体实现
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
return self.binarySearch(nums,0,len(nums)-1,target)
# 新定义一个二分查找的函数
def binarySearch(self,nums,left,right,target):
if left>right:
return -1
mid = (left+right)//2
if nums[mid] == target:
return mid
if nums[mid]>=nums[left] : #左边是有序的
if nums[left]<=target and target<= nums[mid]: # 判断目标值在左半部分
return self.binarySearch(nums,left,mid-1,target) # 递归,
else : # 否则,在右半部分
return self.binarySearch(nums,mid+1,right,target)
else: #右边是有序的,同上述思想一致
if nums[mid]<=target and target<=nums[right]:
return self.binarySearch(nums,mid+1,right,target)
else:
return self.binarySearch(nums,left,mid-1,target)
题外记
这是一定很有意思的题目,拿到的第一感觉有种无从下手的感觉。理清思路后,发现实现其实很简单。不经常在类里边写函数,所以一些问题会不经意的出现。多去系统实操,去发现自己的不足!!!