binary search - leetcode 33. Search in Rotated Sorted Array

1. Question

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

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

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

2. Solution

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if not nums:
            return -1
        def find_rotate_position(nums, l, r):
            mid = r-l+1
            while l <= r:
                if nums[l] > nums[r]:
                    mid = (l+r+1)//2
                    if nums[l] < nums[mid]:
                        l = mid + 1
                    else:
                        r = mid -1
                else:
                    return mid

        import bisect
        rotate_index = find_rotate_position(nums, 0, len(nums)-1)
        if rotate_index != len(nums) and nums[rotate_index] == target:
            return rotate_index
        else:
            i = bisect.bisect_left(nums, target, 0, rotate_index)
            if i != len(nums) and nums[i] == target:
                return i
            else:
                if rotate_index < len(nums):
                    i = bisect.bisect_left(nums, target, rotate_index+1, len(nums))
                    if i != len(nums) and nums[i] == target:
                        return i

        return -1
        

3. Test case

    def test_search():
		solution = Solution()
		
        nums = [4, 5, 6, 7, 0, 1, 2]
        target = 0
        res = solution.search(nums, target)
        assertEqual(res, 4)
        
        nums = [4, 5, 6, 7, 0, 1, 2]
        target = 3
        res = solution.search(nums, target)
        assertEqual(res, -1)
        
        nums = []
        target = 5
        res = solution.search(nums, target)
        assertEqual(res, -1)
        
        nums = [1]
        target = 0
        res = solution.search(nums, target)
        assertEqual(res, -1)

test_search()

4. Explanation

  1. find the rotate position by binary search.
  2. search in the left part of rotate position by binary search.
  3. search in the right part of rotate position by binary search.

5. Basics of binary search

  1. mid = left + right + 1 // 2 : this can handle those special situation related with odd or even lists.
  2. left = mid + 1 & right = mid - 1 : this can make pointer move forward.
  3. i = bisect.left(list, target, low, high) : search in [low, high) , use " i != len(nums) and nums[i] != target " to find the index.

你可能感兴趣的:(python,算法)