Leetcode Tag Search | Back

33. Search in Rotated Sorted Array

Category: /leetcode

Leetcode Link

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 = 0
Output: 4
Example 2:

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

Input: nums = [1], target = 0
Output: -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

Solution

method 1. intuition

  • find the pivot index
  • check which part the target belongs to
  • perform regular binary search on the half.
def search(self, nums, target):
  def find_pivot(left, right):
    if nums[left] < nums[right]: return 0
    while left <= right:
      mid = (left + right) // 2
      if nums[mid] > nums[mid + 1]: 
        return mid + 1
      else:
        if nums[mid] < nums[left]:
          right = mid - 1
        else:
          left = mid + 1
    return -1

  if not nums: return -1
  n = len(nums)
  if n == 1: 
    return 0 if nums[0] == target else -1
  if nums[-1] < nums[0]:
    pv_idx = find_pivot(0, n)
    if target < nums[0]:
      return binary_search(pv_idx, n-1)
    else:
      return binary_search(0, pv_idx-1)
  else:
    return binary_search(0, n-1)

method 2.

If the follow-up question is to find a one-pass solution, need to first check mid is in the 1st ascending part, or the 2nd half. Then compare target with (start, mid, end). Use the sorted half to check target.

def search(self, nums, target):
  start, end = 0, len(nums) - 1
  while start <= end:
    mid = (start + end) // 2
    if nums[mid] == target:
      return mid
    elif nums[mid] >= nums[start]: 
      # 1st half is sorted
      if nums[start] <= target < nums[mid]:
      # note <= and <
        end = mid - 1
      else:
        start = mid + 1
    else:
      if nums[mid] < target <= nums[end]:
        # 2nd half is sorted
        start = mid + 1
      else:
        end = mid -1
  return -1

讨论

提示

  • 如果看不到讨论部分, 请暂时关掉adblock in Firefox/Chrome
  • 本网站使用Javascript实现评论功能, 此处外链对提高您的网站PR没有帮助. (潜台词: 请不要灌水, 谢谢)