Taro Logo

Find Minimum in Rotated Sorted Array II

Hard
Apple logo
Apple
1 view
Topics:
ArraysBinary Search

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. This means the array is shifted by some number of positions. For example, the array nums = [0,1,4,4,5,6,7] might become [4,5,6,7,0,1,4] if it was rotated 4 times.

Given the sorted rotated array nums that may contain duplicates, return the minimum element of this array. You must implement an algorithm that decreases the overall operation steps as much as possible.

Example 1:

Input: nums = [1,3,5]
Output: 1

Example 2:

Input: nums = [2,2,2,0,1]
Output: 0

Constraints:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums is sorted and rotated between 1 and n times.

How would you approach this problem? What is the time and space complexity of your solution?

Solution


Naive Approach

The most straightforward approach is to iterate through the entire array and keep track of the minimum element seen so far. This approach works regardless of whether the array is rotated or contains duplicates.

Code (Python)

def find_minimum_naive(nums):
    min_val = nums[0]
    for i in range(1, len(nums)):
        if nums[i] < min_val:
            min_val = nums[i]
    return min_val

Time Complexity

O(n), where n is the length of the array, as we iterate through each element once.

Space Complexity

O(1), as we only use a constant amount of extra space to store the minimum value.

Optimal Approach: Binary Search

Since the array is sorted and rotated, we can leverage binary search to find the minimum element more efficiently. The key idea is to compare the middle element with the left and right boundaries of the search space.

However, the presence of duplicates complicates the binary search. If nums[mid] == nums[left], we can't determine which half contains the minimum, so we simply increment left to shrink the search space. Similarly, if nums[mid] == nums[right], we decrement right.

Algorithm

  1. Initialize left to 0 and right to len(nums) - 1.
  2. While left < right:
    • Calculate mid = (left + right) // 2.
    • If nums[mid] > nums[right], the minimum is in the right half, so left = mid + 1.
    • Else if nums[mid] < nums[right], the minimum is in the left half (including mid), so right = mid.
    • Else (if nums[mid] == nums[right]): decrement right.
  3. Return nums[left] (or nums[right] since left == right).

Code (Python)

def find_minimum_rotated_sorted_array_with_duplicates(nums):
    left, right = 0, len(nums) - 1

    while left < right:
        mid = (left + right) // 2

        if nums[mid] > nums[right]:
            left = mid + 1
        elif nums[mid] < nums[right]:
            right = mid
        else:
            right -= 1

    return nums[left]

Time Complexity

In the best case (no duplicates), the time complexity is O(log n). However, in the worst case (many duplicates), the time complexity can degrade to O(n), as we might have to increment left or decrement right linearly.

Space Complexity

O(1), as we only use a constant amount of extra space for the pointers.

Edge Cases

  • Empty Array: The problem states that 1 <= n <= 5000, so the array will never be empty. However, it's good practice to consider this. If the array could be empty, add a check at the beginning: if not nums: return None.
  • Single Element Array: The algorithm works correctly for a single-element array.
  • Array with all same elements: The algorithm should handle an array where all elements are the same, returning the only element.