def find_min_rotated(arr: List[int]) → int:
“”"
This makes use of the first element in the array to be compared against the mid instead of the last element.
This does not work with a non-pivoted array hence the return boundary_index if boundary_index != -1 else 0
“”"
left, right = 0, len(arr)-1
boundary_index = -1
while left <= right:
mid = (left + right) // 2
if arr[mid] >= arr[0]:
left = mid + 1
else:
boundary_index = mid
right = mid - 1
return boundary_index if boundary_index != -1 else 0
The solution mentions that numbers could be repeated Eg: “Return the minimum index if the minimum number is repeated” but the provided solution fails for [3,1,3] or [3,3,1,3] case. This is because the condition array is no longer False followed by True’s [F, F…T,T,T] but instead they will be [T, T, T] or [T, T, T, T]. The solution only works for unique elements.
The solution does’t work if the smallest number is in the first haft and the largest number is in the middle
eg. 30 10 50 40 20, it return 4 when the result should be 1
As others have already reported, this algorithm fails for many cases when first and last element are the same.
e.g., for [30 30 30 30 20 30] it outputs 0 rather than 4
In binary search, when looking for first occurance of a boolean value, we must first ensure that it exists.
When using last element, this is always the case as we are guaranteed to find element that is <= last element. When using the first element in the list, this is not the case that an element < first element exists as the list might be sorted.
For test case like [3,3,1,2,3,3,3], we can have a patch like this:
def find_min_rotated(arr: List[int]) → int:
left = 0
right = len(arr)-1
# this is a patch for [3,3,1,2,3,3,3]
while arr[left] == arr[right]:
left += 1
while arr[right] == arr[left]:
right -= 1
res = -1
while left <= right:
mid = left + (right-left)//2
if arr[mid] <= arr[-1]:
res = mid
right = mid -1
else:
left = mid + 1
return res