Suppose an array of length n
sorted in ascending order is rotated between 1
and n
times. 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.[0,1,4,4,5,6,7]
if it was rotated 7
times.Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]]
1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
.
Given the sorted rotated array nums
that may contain duplicates, return the minimum element of this array.
You must decrease the overall operation steps as much as possible.
For example:
Example 1:
Input: nums = [1,3,5]
Output: 1
Example 2:
Input: nums = [2,2,2,0,1]
Output: 0
Can you provide an efficient algorithm to solve this problem, considering the presence of duplicates?
The simplest approach is to iterate through the entire array and keep track of the minimum element encountered. This approach works regardless of whether the array is rotated or contains duplicates.
min_element
to the first element of the array.min_element
. If the current element is smaller, update min_element
.min_element
.def find_minimum_brute_force(nums):
min_element = nums[0]
for i in range(1, len(nums)):
if nums[i] < min_element:
min_element = nums[i]
return min_element
O(n), where n is the length of the array, as we iterate through the array once.
O(1), as we use a constant amount of extra space to store the minimum element.
We can leverage binary search to find the minimum element more efficiently. The presence of duplicates makes the problem more challenging, as it may prevent us from discarding half of the array in each step.
left
to 0 and right
to n - 1
.left < right
:
mid = (left + right) // 2
.nums[mid] > nums[right]
, then the minimum element must be in the right half of the array. Update left = mid + 1
.nums[mid] < nums[right]
, then the minimum element must be in the left half of the array (including mid
). Update right = mid
.nums[mid] == nums[right]
, we cannot determine which half contains the minimum element. In this case, we simply decrement right
to shrink the search space.nums[left]
. At the end of the loop, left
and right
will point to the same index, which contains the minimum element.def find_minimum_binary_search(nums):
left = 0
right = 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 # nums[mid] == nums[right]
return nums[left]
The worst-case time complexity is O(n), which occurs when the array contains many duplicate elements. In the worst case, nums[mid] == nums[right]
repeatedly, and we reduce the search space by only one element in each step. However, in many cases, the time complexity will be better than O(n), potentially approaching O(log n) if duplicates are rare.
O(1), as we use a constant amount of extra space to store the indices left
, right
, and mid
.
1 <= n <= 5000
, so we don't need to handle an empty array explicitly. However, it's good to be aware of such edge cases during an interview.while
loop will not execute, and the function will return the single element.nums[mid] < nums[right]
will be true in the first iteration, and right
will be updated to mid
until left == right
.