Advertisement
Guest User

Untitled

a guest
Apr 4th, 2020
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.58 KB | None | 0 0
  1. def bisect_f(f, lo, hi):
  2.     assert f(lo) and not f(hi)
  3.     while hi - lo > 1:
  4.         mid = (lo + hi) // 2
  5.         if f(mid):
  6.             lo = mid
  7.         else:
  8.             hi = mid
  9.         assert f(lo) and not f(hi)
  10.     assert hi - lo == 1
  11.     assert f(lo) and not f(hi)
  12.     return lo
  13.  
  14.  
  15. class Solution(object):
  16.     def search(self, nums, target):
  17.         """
  18.        :type nums: List[int]
  19.        :type target: int
  20.        :rtype: int
  21.        """
  22.         if not nums:
  23.             return -1
  24.         if len(nums) == 1:
  25.             if nums[0] == target:
  26.                 return 0
  27.             return -1
  28.  
  29.         def getPivot():
  30.             #
  31.             #   *
  32.             #  *
  33.             # *
  34.             #      *
  35.             #     *
  36.             #    *
  37.             # On left side if => nums[0]
  38.             # On right side if <= nums[-1]
  39.             # Find first i where nums[i] on the left and nums[i+1] is on the right
  40.             #
  41.             # Note we can't do this efficiently if duplicates are allowed
  42.             # For example consider the list where you have
  43.             #   [0,0,...,0,0,1,-1,0,0,...,0,0]
  44.             # It's not possible to find the pivot sublinearly because local info around indices are all the same
  45.  
  46.             if nums[0] < nums[-1]:
  47.                 # Not rotated
  48.                 return 0
  49.             assert nums[-1] < nums[0]
  50.  
  51.             def isOnLeft(i):
  52.                 return nums[0] <= nums[i]
  53.  
  54.             def isOnRight(i):
  55.                 # This can also be written as nums[i] < nums[0] (not isOnLeft)
  56.                 # because nums[-1] and num[0] are adjacent in the sorted list with no repeats
  57.                 return nums[i] <= nums[-1]
  58.  
  59.             lo = 0
  60.             hi = len(nums) - 1
  61.  
  62.             assert isOnLeft(lo) and isOnRight(hi)
  63.             index = bisect_f(isOnLeft, lo, hi)
  64.             assert isOnLeft(index) and isOnRight(index + 1)
  65.  
  66.             return index + 1
  67.  
  68.         pivot = getPivot()
  69.         # print(nums[:pivot], nums[pivot:])
  70.  
  71.         def remap(index):
  72.             return (index + pivot) % len(nums)
  73.  
  74.         lo = 0
  75.         hi = len(nums) - 1
  76.         if nums[remap(hi)] == target:
  77.             return remap(hi)
  78.         if target < nums[remap(lo)] or nums[remap(hi)] <= target:
  79.             return -1
  80.  
  81.         assert nums[remap(lo)] <= target < nums[remap(hi)]
  82.         index = bisect_f(lambda index: nums[remap(index)] <= target, lo, hi)
  83.         assert nums[remap(index)] <= target < nums[remap(index + 1)]
  84.  
  85.         if nums[remap(index)] == target:
  86.             return remap(index)
  87.         return -1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement