Description
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.
Constraints
0 <= nums.length <= 105-109 <= nums[i] <= 109numsis a non-decreasing array.-109 <= target <= 109
Examples
- Example 1:
Input:nums = [5, 7, 7, 8, 8, 10],target = 8
Output:[3, 4] - Example 2:
Input:nums = [5, 7, 7, 8, 8, 10],target = 6
Output:[-1, -1] - Example 3:
Input:nums = [],target = 0
Output:[-1, -1]
Solution 1: Brute-Force
Thought
The input parameter nums has already been sorted in increasing order. Therefore, the most intuitive approach is to iterate through the entire array from both the start and end separately. Record the index of the first occurrence of a value equal to the target from both ends and return these two indices at the end.
Steps
- Initialize two pointers,
iandj, starting at0andlen(nums) - 1, respectively. - Initialize the variable
positionsas[-1, -1]to serve as a record for the found index positions. - Start by sequentially iterating through the entire
numsstarting fromi. Ifnums[i]is equal to thetarget, record the current positioniinpositions[0]and then break the iteration. - For the second iteration, iterate through
numsin reverse, starting fromj. Ifnums[j]is equal to thetarget, record the current positionjinpositions[1]and then break the iteration. - Finally, return
positions.
Codes
def search_range(nums: List[int], target: int) -> List[int]:
i = 0
j = len(nums) - 1
positions = [-1, -1]
while i < len(nums):
if nums[i] == target:
positions[0] = i
break
i += 1
while j >= 0:
if nums[j] == target:
positions[1] = j
break
j -= 1
return positionsPythonComplexities
- Time Complexity:
O(N), whereNrepresents the length ofnums. - Space Complexity:
O(1).
Solution 2: Binary Search
Thought
The prompt mentioning an optimal time complexity of O(log N) strongly suggests the use of binary search, especially considering the task involves finding a target in a sorted array. We can employ binary search twice successively to approach the closest and farthest targets to obtain the final answer.
Steps
- Initialize the variable
positionsas[-1, -1]to serve as a record for the found index positions. - The first search:
- Initialize the
leftandrightpointers to0andlen(nums) - 1, respectively, to define the search range. - When
leftis less than or equal toright:- Calculate the
midposition as(left + right) // 2. - If
nums[mid]is less than thetarget, move theleftpointerleftto the positionmid + 1. - If
nums[mid]is greater than thetarget, move therightpointerrightto the positionmid - 1. - If
nums[mid]is equal to thetarget:- As we’re searching for the first occurrence of the
target, we need to check if the element beforemid(nums[mid - 1]) is also equal to thetarget. If it is, move therightpointer to positionmid - 1and continue the search. - If not, it means we’ve found the position of the first occurrence of the
target. Record it inpositions[0]and terminate the search.
- As we’re searching for the first occurrence of the
- Calculate the
- Initialize the
- The second search:
- The search logic is identical to the first search. The only difference is that now we’re searching for the position of the last occurrence of the
target. Whenmidpoints to a position equal to thetargetand the next position (nums[mid + 1]) is also equal to thetarget, move theleftpointer to positionmid + 1and continue the search.
- The search logic is identical to the first search. The only difference is that now we’re searching for the position of the last occurrence of the
- Finally, return
positions.
Codes
def search_range(nums: List[int], target: int) -> List[int]:
positions = [-1, -1]
# find the first position
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
if mid > 0 and nums[mid - 1] == target:
right = mid - 1
else:
positions[0] = mid
break
# find the last position
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
else:
if mid < len(nums) - 1 and nums[mid + 1] == target:
left = mid + 1
else:
positions[1] = mid
break
return positionsPythonComplexities
- Time Complexity:
O(logN), whereNrepresents the length ofnums. - Space Complexity:
O(1).