1. 程式人生 > >Leetcode 33:搜尋旋轉排列陣列(最詳細的解法!!!)

Leetcode 33:搜尋旋轉排列陣列(最詳細的解法!!!)

假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。

( 例如,陣列 [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

解題思路

由於問題給定的時間複雜度要求是O(logn)級別,所以你當然不能通過直接遍歷得到。我們首先想到的是通過二分搜尋法,但是這裡的二分搜尋法需要一些變化。對於第一個例子來說

4   5   6   7   0   1   2
l           m           r

我們首先計算nums[m]=7,然後比較nums[m]>=nums[l],如果成立,說明[l:m]這個區間正常。我們先要在[l:m]這個區間找target,也就是我們要判斷nums[l]<=target<=nums[m],如果成立說明在這個區間內,我們讓r=m-1,否則的話l=m+1

4   5   6   7   0   1   2
                l   m   r

回到上一步nums[m]>=num[l]成立,nums[l]<=target<=nums[m]

也成立,我們將r=m-1

4   5   6   7   0   1   2
                l
                r
                m

此時l==r,而target=0,即返回m

如果我們發現nums[m]<nums[l],說明[m:r]這個區間正常。例如

5   6   7   0   1   2   4
l           m           r

我們就要先判斷target是不是在[m:r]這個區間內,也就是判斷nums[m]<=target<=nums[r],如果成立l=m+1,否則的話r=m-1

總體的思路就是先找出中間元素,然後判斷左右哪個是標準空間(排好序的空間),接著判斷元素是不是在標準空間中(因為這是可以確定的)。接著繼續回到之前步驟,直到找到為止。

class Solution:
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if not nums:
            return -1

        low, high = 0, len(nums) - 1

        while low <= high:
            mid = (low + high) // 2
            if target == nums[mid]:
                return mid

            if nums[low] <= nums[mid]:
                if nums[low] <= target <= nums[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:
                if nums[mid] <= target <= nums[high]:
                    low = mid + 1
                else:
                    high = mid - 1

        return -1

其實就是二分搜尋的泛化。

reference:

如有問題,希望大家指出!!!