Given an array of integers nums
sorted in non-decreasing order, find the starting and ending position of a given target
value.
If target
is not found in the array, return [-1, -1]
.
You must write an algorithm with O(log n)
runtime complexity.
For example:
nums = [5,7,7,8,8,10], target = 8
should return [3,4]
nums = [5,7,7,8,8,10], target = 6
should return [-1,-1]
nums = [], target = 0
should return [-1,-1]
Explain your approach, its time complexity, and handle any potential edge cases.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine searching a phone book for someone's name. With the brute force way, you'd simply look at every name, one by one, until you found it. To find the first and last time the name appears, you'd keep looking at every name even after you found the first one until you reach the end.
Here's how the algorithm would work step-by-step:
def find_first_and_last_brute_force(numbers, target):
first_position = -1
last_position = -1
for index in range(len(numbers)):
if numbers[index] == target:
# Record the first occurence
if first_position == -1:
first_position = index
# Continuously update the last position
last_position = index
return [first_position, last_position]
The key to solving this problem quickly is to take advantage of the sorted nature of the data. We can efficiently find the first and last positions of the target value by performing two separate searches that cut the search space in half each time.
Here's how the algorithm would work step-by-step:
def find_first_and_last_position(
sorted_array, target_value
):
first_position = find_first(sorted_array, target_value)
last_position = find_last(sorted_array, target_value)
return [first_position, last_position]
def find_first(sorted_array, target_value):
left_index = 0
right_index = len(sorted_array) - 1
first_position = -1
while left_index <= right_index:
middle_index = (left_index + right_index) // 2
if sorted_array[middle_index] == target_value:
# Potential first occurrence, keep searching left.
first_position = middle_index
right_index = middle_index - 1
elif sorted_array[middle_index] < target_value:
left_index = middle_index + 1
else:
right_index = middle_index - 1
return first_position
def find_last(sorted_array, target_value):
left_index = 0
right_index = len(sorted_array) - 1
last_position = -1
while left_index <= right_index:
middle_index = (left_index + right_index) // 2
if sorted_array[middle_index] == target_value:
# Potential last occurrence, keep searching right.
last_position = middle_index
left_index = middle_index + 1
elif sorted_array[middle_index] < target_value:
left_index = middle_index + 1
else:
right_index = middle_index - 1
return last_position
Case | How to Handle |
---|---|
Null or empty input array | Return [-1, -1] immediately as the target cannot exist in an empty array. |
Target is smaller than the smallest element in the array | Binary search will narrow the search space and eventually determine that the target is not found, returning [-1, -1]. |
Target is larger than the largest element in the array | Binary search will narrow the search space and eventually determine that the target is not found, returning [-1, -1]. |
Array contains a single element equal to the target | Binary search will find the element, and the start and end indices will be the same. |
Array contains a single element not equal to the target | Binary search will not find the element, returning [-1, -1]. |
Array contains all elements equal to the target | Binary searches for the start and end will correctly identify the first and last indices of the repeated target values. |
Array contains duplicate numbers, but none are the target | Binary search will narrow the search space and eventually determine that the target is not found, returning [-1, -1]. |
Target is present only at the start or end of the array | The binary search strategy handles this case, as it correctly identifies the first and last occurrence independent of array position. |