Leetcode 33 搜尋旋轉排序陣列 思路詳解+反思總結 python實現
阿新 • • 發佈:2019-01-22
本人一直在努力地積累Leetcode上用Python實現的題,並且會盡力講清每道題的原理,絕不像其他某些部落格簡略地帶過。
如果覺得講的清楚,歡迎關注。
題目:
假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。
( 例如,陣列 [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
思路:首先了解到這道題要求的解法是logn級別。logn與什麼最搭?當然是二分的思想!但是很多朋友可能會說,排序陣列的二分查詢我很熟,但這道題可能經過了旋轉啊。沒錯,這陣列經過旋轉後,形成了2段遞增的序列。我們得先找到2個序列的分界點,將陣列分成2部分分別二分查詢。那麼這道題的難題就成功轉移到如何找到那個分界點。可能很多朋友又會說,直接從後或者從前按順序找,當突然前面的數字比當前大就說明這是斷點嘛!但題目要求logn,按順序找的話是n。
程式碼:
binarysearch是用來對2陣列分別二分查詢的。找斷點比較有意思:我們通過l 和 R 求 mid, 通過比較mid和最右邊的r的值,我們去判斷第二段遞增序列的第一個點。最右邊的r永遠是在遞增序列中,如果num[mid] < num[r],說明我們這個mid與r在同一個遞增序列,我們減少r,令r=mid,縮小範圍去查詢斷點。如果num[mid] > num[r],說明mid與r在2個遞增序列,增大L,令l= mid+1, 不斷逼近斷點。class Solution: def search(self, nums, target): """ :type nums: List[int] :type target: int :rtype: int """ #先找到兩個第二個升序陣列的第一項的index l = 0 r = len(nums) -1 while l < r: mid = (l + r)//2 if nums[mid] > nums[r]: l = mid + 1 else: r = mid pol = l ans = self.binary_search(target, nums[:pol]) if ans == -1: ans = self.binary_search(target, nums[pol:]) if ans != -1: ans += len(nums[:pol]) return ans def binary_search(self, target, nums): index = -1 l = 0 r = len(nums) - 1 while l <= r: mid = (l+r)//2 if nums[mid] < target: l = mid + 1 elif nums[mid] > target: r = mid - 1 else: index = mid break return index