1. 程式人生 > >LeetCode33-搜尋旋轉排序陣列

LeetCode33-搜尋旋轉排序陣列

昨天參加學院舉辦的演算法比賽

從上午10點一直考到下午3點

唯一的感受就是

中午發的兩袋皇冠蛋糕和牛奶

真TM的好吃!!!


33-搜尋旋轉排序陣列

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

( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。

搜尋一個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 -1 。

你可以假設陣列中不存在重複的元素。

你的演算法時間複雜度必須是 O(log n) 級別。

示例 1:

4,5,6,7,0,1,2]

示例 2:

4,5,6,7,0,1,2]

這一題出題人的意思其實是很好,想讓我們用二分法找值,但是檢測系統有點辣雞啊!直接用個index()找值也是ok的,而且執行效率很快。

直接找值程式碼如下:

class Solution:
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if len(nums) == 0 or target is None:
            return -1
        if target in nums:
            return nums.index(target)
        else:
            return -1


if __name__ == "__main__":
    nums = [4,5,6,7,0,1,2]
    target = 3
    result = Solution().search(nums, target)
    print(result)      

這個的執行效率在90%以上。

 

 

但是為了不辜負出題人的一番心血,我們還是得按照題目的意思來好好做。因為題目規定:演算法時間複雜度必須是 O(log n) 級別,所以我們很容易想到用二分法來解題。因為給定的陣列其實是兩段升序陣列拼接起來的,這就給了我們一箇中間值與起始值和終點值的大小關係。還有一點關鍵就是:左邊的升序陣列一定是比右邊的升序陣列的值要大。大家一想想就清楚了,所以如果中間值比終點值要大,說明中間值肯定是在第一個升序數組裡面;如果要小,說明一定是在第二個升序數組裡,以此類推。挺簡單的,直接看程式碼吧!

程式碼如下:

class Solution:
    # 因為題目要求時間複雜度為O(logN),故想到二分法
    # 首先得找到二段旋轉排序陣列的分解值
    # 找到分界值後,即可分別對兩段陣列做二分法搜尋
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        # 只要給定的nums陣列或者給定的target目標值為空,說明查無此值
        if len(nums) == 0 or target is None:
            return -1
        # 首先查詢分界值,也是採用二分法查詢,分別定義起始點start和終點end
        start = 0
        end = len(nums) - 1
        binart_index = 0
        while start < end:
            mid = (start+end)//2
            if nums[mid] >= nums[mid+1]:
                binart_index = mid
                break
            if nums[mid] > nums[end]:
                start = mid
            else:
                end = mid
        print("binart_index", binart_index)
        # 定義查詢target的目標值的下標值初始值為-1
        target_index = -1
        nums_left = nums[:binart_index+1]
        nums_right = nums[binart_index+1:]
        if len(nums_left) > 0:
            print("nums_left", nums_left)
            target_index = self.binary_search(nums_left, target)
            print("target_index", target_index)
        if target_index < 0 and len(nums_right) > 0:
            print("nums_right", nums_right)
            target_index = self.binary_search(nums_right, target)
            print("target_index", target_index)
            if target_index > -1:
                target_index += binart_index + 1
        return max(target_index, -1)

    # 二分法在nums數組裡查詢目標值
    def binary_search(self, nums, target):
        start = 0
        end = len(nums) - 1
        target_index = -1
        while start <= end:
            mid = (start+end)//2
            if nums[mid] == target:
                target_index = mid
                break
            elif nums[mid] > target:
                end = mid -1
            else:
                start = mid + 1
            print("mid", mid)
        return target_index


if __name__ == "__main__":
    nums = [3, 4, 5, 0, 1]
    target = 2
    result = Solution().search(nums, target)
    print(result)

執行效率一般,在40%左右。