题目描述:
链接:https://leetcode.com/problems/search-in-rotated-sorted-array/description/
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
Your algorithm’s runtime complexity must be in the order of O(log n).
- 案例
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
分析
平时使用二分法的时候,直接判断中点和目标的关系,就可以知道目标在左半边还是右半边,这需要一个条件,数组有序的。在这题中,因为发生了旋转,原来的数组不在有序。但升序数组旋转后如果左边的点比右边的点小,说明这两个点之间是有序的,不存在旋转点。如果左边的点比右边的大,说明这两个点之间有一个旋转点,导致了不再有序。因为只有一个旋转点,从中间一分为二后,肯定有一半是有序的。所以,我们还是可以用二分法,不过要先判断左半边有序还是右半边有序。如果左半边有序,则直接将目标和左半边的边界比较,就知道目标在不在左半边了,如果不在左半边肯定在右半边。同理,如果右半边有序,则直接将目标和右半边的边界比较,就知道目标在不在右半边了,如果不在右半边肯定在左半边。这样就完成了二分搜索。
实现(python)
def search(li,start,end,target):
mid = start + (end-start)//2
if start > end:
return -1
if li[mid] == target:
return mid
# 如果左半部分是有序的
if li[start] < li[mid]:
## 如果在左半部分的边界内
if (li[start] <= target) and (target < li[mid]):
return search(li,start,mid-1,target)
else:
return search(li,mid+1,end,target)
# 如果右半部分是有序的
else:
if (li[mid] < target) and (target <= li[end]):
return search(li, mid+1, end, target)
else:
return search(li, start, mid-1, target)
li = [4,5,6,7,0,1,2]
target = 0
search(li,0,len(li)-1,target)