leetcode33. Search in Rotated Sorted Array相同的思路,不同的複雜度

原題鏈接
第一眼看到這個題,本能的想到二分搜索。自己的解法是這樣:

  1. 先找到最小的值反轉後的的位置,例如題目中的數組[4,5,6,7,0,1,2]中0在第四位,記爲cur = 4,如何尋找呢?
    順序找肯定是不可取的,但是我第一次沒有轉個來這個彎,居然採用順序查找的方式(那爲什麼不直接順序查找target呢?真是笨)
  2. 找到cur的位置便可以使用經典的二分查找法,但必須在翻轉前後的座標之間做一個轉換,這個轉換的工作在下面的代碼裏會有體現。
class Solution:
    def search(self, nums: 'List[int]', target: 'int') -> 'int':
        nums_L = len(nums)
        cur = 0
        for i in range(1, nums_L):
            if nums[i] < nums[i - 1]:
                cur = i
                break
	#上面求cur
        if cur != 0:
            Solution.tran_cur = Solution.tran_cur1
        elif nums[0] < nums[nums_L -1]:
            Solution.tran_cur = Solution.tran_cur2
        else:
            Solution.tran_cur = Solution.tran_cur3
        #根據cur的不同選取不同的轉換函數,實際上這一步可用方法二中的一行代碼就可以替換掉
        l_, r_ = (0), (nums_L - 1)
        l, r = Solution.tran_cur(l_, nums_L, cur), Solution.tran_cur(r_, nums_L, cur)

        while l_ <= r_:
            mid_ = int((l_ + r_) / 2)
            mid = Solution.tran_cur(mid_, nums_L, cur)
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                l_ = mid_ + 1
                l = Solution.tran_cur(l_, nums_L, cur)
            else:
                r_ = mid_ - 1
                r = Solution.tran_cur(r_, nums_L, cur)

        return -1
#下面是三個轉換函數
    def tran_cur1(i, nums_L, cur):
        l = i - (nums_L - cur)
        r = i + cur
        if l >= 0 and l < nums_L:
            return l
        else:
            return r
    def tran_cur2(i, nums_L, cur):
        return i
    def tran_cur3(i, nums_L, cur):
        return nums_L - i -1

不得不說,我自己都覺得這代碼實在太他媽的囉嗦,但精簡的代碼畢竟都是由繁入簡一步步得到的。別看這代碼囉嗦,而且計算cur時還是暴力算的,但是居然還beat了leetcode上67%的人,我感覺直接找都應該比這個方法要快!下面貼一個根據評論區某位老兄的代碼改來的python版代碼,思路其實相同。

class Solution:
    def search(self, nums: 'List[int]', target: 'int') -> 'int':
        nums_L = len(nums)
        lo, hi = 0, nums_L-1
#採用二分的方式來求翻轉後數組中的最小值,
        while lo<hi:
            mid = int((lo+hi)/2)
            if nums[mid]>nums[hi]: lo = mid+1
            else: hi = mid
        cur = lo
        lo, hi = 0, nums_L-1
        while lo <= hi:
            mid = int((lo+hi)/2)
            #下面這行代碼便是翻轉前後座標的轉換,一行搞定,實在令人佩服!
            realmid = (mid+cur)%nums_L
            if nums[realmid]==target: return realmid
            elif nums[realmid]<target: lo = mid+1
            else: hi = mid-1
        return -1

這題雖然不難,但是花的時間卻真不少,感觸也很深。做這種題目一般都是通過一個具體的實例來想一個較爲通用的解法,很多時候思路對了,但是因爲不能夠覆蓋的了所有的情況又會導致很多錯誤的出現,而這些錯誤往往會通過一些特殊的做法來解決,不僅導致代碼量的增加,而且在解決的過程中,還有可能會引出其他的一些錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章