LeetCode 搜索旋轉排序數組

假設按照升序排序的數組在預先未知的某個點上進行了旋轉。算法

( 例如,數組 [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
相關文章
相關標籤/搜索