假設按照升序排序的數組在預先未知的某個點上進行了旋轉。算法
( 例如,數組 [0,1,2,4,5,6,7]
可能變爲 [4,5,6,7,0,1,2]
)。數組
搜索一個給定的目標值,若是數組中存在這個目標值,則返回它的索引,不然返回 -1
。spa
你能夠假設數組中不存在重複的元素。code
你的算法時間複雜度必須是 O(log n) 級別。blog
示例 1:排序
輸入: nums = [, target = 0 輸出: 4 4,5,6,7,0,1,2]
示例 2:遞歸
輸入: nums = [, target = 3 輸出: -14,5,6,7,0,1,2]
回憶一下,以前有一道尋找旋轉排序數組中最小值的問題,咱們當時使用num[left]和num[mid]的大小關係來判斷此時mid指向的元素是在數組的前半段仍是後半段。這道題和上一道稍微有點不同,由於在上道題中,咱們能夠控制left與right始終分別指向左右兩段數組。而這裏,顯然是不適合的。所以,咱們能夠先判斷通過二分以後的兩段數組哪一個是排好序的,再判斷target是否在這段排好序的數組當中,是的話,就簡單了,簡單二分搜索便可,不在的話,繼續分析上回沒排好序的數組,遞歸的按照以上的邏輯繼續查找便可。索引
能夠分如下三種狀況討論:get
1. num[mid] = target,那麼找到了,不用繼續找了io
2. num[mid] > num[left] 那麼此時mid左端,一直到left的數組是排好序的。能夠繼續細分爲兩種狀況:
(1)num[mid] > target && target >= num[left],說明此時target在mid左側排好序的數組內。用二分查找處理這段數組便可
(2)若是不符合(1)中的條件,處理mid右側的數組(仍是按照先尋找排序數組,再二分查找的邏輯)
3. 2中的條件不成立,那麼此時mid右端,一直到right的數組是排好序的。能夠繼續細分爲兩種狀況:
(1)num[mid] < target && target <= num[right],說明此時target在mid右側排好序的數組內。用二分查找處理這段數組便可
(2)若是不符合(1)中的條件,處理mid左側的數組(仍是按照先尋找排序數組,再二分查找的邏輯)
1 class Solution(object): 2 def search(self, nums, target): 3 """ 4 :type nums: List[int] 5 :type target: int 6 :rtype: int 7 """ 8 left, right = 0, len(nums) - 1 9 while left <= right: 10 mid = int((left + right) / 2) 11 if nums[mid] == target: 12 return mid 13 if nums[mid] > nums[right]: # 說明左面是排序好的 14 if nums[left] <= target and nums[mid] > target: 15 # 在左邊有序序列中進行折半查找 16 right = mid-1 17 else: 18 # 進入右邊的序列進行查找 19 left = mid+1 20 else: #說明右邊是排序好的 21 if nums[mid] < target and nums[right] >= target: 22 # 進入右邊的有序序列進行查找 23 left = mid+1 24 else: 25 # 進入左邊的序列進行查找 26 right = mid-1 27 return -1