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?
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.
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
O(n), where n is the length of the array, as we iterate through each element once.
O(1), as we only use a constant amount of extra space to store the minimum value.
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
.
left
to 0 and right
to len(nums) - 1
.left < right
:
mid = (left + right) // 2
.nums[mid] > nums[right]
, the minimum is in the right half, so left = mid + 1
.nums[mid] < nums[right]
, the minimum is in the left half (including mid), so right = mid
.nums[mid] == nums[right]
): decrement right
.nums[left]
(or nums[right]
since left == right
).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]
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.
O(1), as we only use a constant amount of extra space for the pointers.
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
.