一.题目:
有一个不含重复数字的升序数组,可能做了一些旋转操作,给定一个数查询是否存在这个数,若存在返回下标否则返回-1.时间复杂度为O(log n).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
二.解题思路:
要求时间复杂度O(log n),提示我们使用二分搜索.这里要注意中间数字所在的区间是属于左边升序区间还是右边升序区间.代码如下:
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
#时间复杂度为O(log n),则考虑使用二分查找
if not nums:
return -1
start = 0
end = len(nums)-1
while start <= end:
mid = (start+end)/2
if nums[mid] == target:
return mid
#当nums[mid]属于左边升序序列时
if nums[mid] >= nums[start]:
if target>=nums[start] and target<nums[mid]:
end = mid -1
else:
start = mid +1
#当nums[mid]属于右边升序序列时
elif nums[mid] <= nums[end]:
if target<=nums[end] and target>nums[mid]:
start = mid +1
else:
end = mid -1
return -1
如果这个数字可以包含重复数字,也就是leetcode上第81题,是上题的升级版.我们可以将其简化为上一题的版本,具体操作就是判断首尾两个元素是否相等,若不相等则将左指针一直往右移动.代码如下:
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: bool
"""
N = len(nums)
l, r = 0, N - 1
while l <= r:
while l < r and nums[l] == nums[r]:
l += 1
mid = l + (r - l) / 2
if nums[mid] == target:
return True
if nums[mid] >= nums[l]:
if nums[l] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
elif nums[mid] <= nums[r]:
if nums[mid] < target <= nums[r]:
l = mid + 1
else:
r = mid - 1
return False