動機

重新體驗binary search

這題可以與153一起看,會有新的理解

Problem

There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is rotated at an unknown pivot index k (0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].

Given the array nums after the rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

You must write an algorithm with O(log n) runtime complexity.

 

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3Output: -1

Example 3:

Input: nums = [1], target = 0Output: -1

 

Constraints:

  • 1 <= nums.length <= 5000
  • -104 <= nums[i] <= 104
  • All values of nums are unique.
  • nums is guaranteed to be rotated at some pivot.
  • -104 <= target <= 104

Sol

bsearch重要的就是

  1. 怎麼求中點
  2. 包含中點的有序範圍
  3. 確認範圍中有沒有target,決定這塊要不要丟

而這題是只要意識到其中一邊一定會有序,就知道一定有一邊可以丟,那就只看target有沒有可能在這裡面,有就進去,沒有就另一邊

另外就是比範圍時,只有中點不用看等於,像一開始看右邊是不是有序是ns[mid] < ns[mid+1] < ns[j-1],但只要遇到長度為2範圍就爆了,mid+1等於j-1啊

def bs(ns, x, i, j):
    if i>j or i < 0 or i > len(ns):
        return -1
    if j-i <= 1:
        return i if ns[i] == x else -1
    elif j-i == 2:
        return i if ns[i] == x else bs(ns,x,i+1,j)
    else:
        mid = i + (j-i)//2
        if ns[mid] == x:
            return mid
        else:
            rightasc = ns[mid] < ns[mid+1] <= ns[j-1]
            inright = ns[mid] < x <= ns[j-1]
            inleft = ns[i] <= x < ns[mid]
            
            if rightasc and inright or not rightasc and not inleft:
                return bs(ns,x,mid+1,j)
            else:
                return bs(ns,x,i,mid)
                    
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return bs(nums,target,0,len(nums))