|
| 1 | +# 33. Search in Rotated Sorted Array |
| 2 | + |
| 3 | +## From scratch iterative solution |
| 4 | +- Runtime: O(log(N)) |
| 5 | +- Space: O(1) |
| 6 | +- N = Number of elements in array |
| 7 | + |
| 8 | +Take the example, "5,6,1,2,3,4" and "3,4,5,6,1,2" and "1,2,3,4,5,6". |
| 9 | +If you had a sorted array, it would be easy to just binary search that. But if its rotated, you can still binary search the array but only parts of it. What is stopping you from immediately binary searching the array is that you don't know where the rotation point is. Once you can find it then the solution becomes easier as you can just binary search the sub-array containing your target. You can find the beginning index of the rotated sub-array by binary searching it. |
| 10 | + |
| 11 | +``` |
| 12 | +class Solution: |
| 13 | + def search(self, nums: List[int], target: int) -> int: |
| 14 | + def get_first_sorted_index(nums): |
| 15 | + left_i, right_i = 0, len(nums)-1 |
| 16 | + while left_i <= right_i: |
| 17 | + mid_i = int(abs(left_i + (right_i - left_i)/2)) |
| 18 | + if mid_i != 0 and nums[mid_i-1] > nums[mid_i]: |
| 19 | + return mid_i |
| 20 | + if nums[mid_i] < nums[left_i]: # go left |
| 21 | + right_i = mid_i-1 |
| 22 | + elif nums[mid_i] > nums[right_i]: # go right |
| 23 | + left_i = mid_i+1 |
| 24 | + else: # sub-array is sorted, keep going left |
| 25 | + right_i = mid_i-1 |
| 26 | + return 0 |
| 27 | + |
| 28 | + def binary_search_from_range(start, end, target, nums): |
| 29 | + while start <= end: |
| 30 | + mid_i = int(abs(start + (end - start)/2)) |
| 31 | + if nums[mid_i] == target: |
| 32 | + return mid_i |
| 33 | + if nums[mid_i] < target: # go right |
| 34 | + start = mid_i+1 |
| 35 | + elif nums[mid_i] > target: # go left |
| 36 | + end = mid_i-1 |
| 37 | + return -1 |
| 38 | + |
| 39 | + if len(nums) == 0: |
| 40 | + return -1 |
| 41 | + first_sorted_index = get_first_sorted_index(nums) |
| 42 | + if target <= nums[-1]: # right side |
| 43 | + return binary_search_from_range(first_sorted_index, len(nums)-1, target, nums) |
| 44 | + # left side |
| 45 | + return binary_search_from_range(0, first_sorted_index, target, nums) |
| 46 | +``` |
0 commit comments