Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find First and Last Position of Element in Sorted Array in Python
Finding the first and last position of an element in a sorted array is a classic problem that can be efficiently solved using binary search. Given a sorted array and a target value, we need to return the starting and ending indices of the target. If the target is not found, we return [-1, -1].
For example, if the array is [2,2,2,3,4,4,4,4,5,5,6] and target is 4, the output should be [4,7] since 4 appears from index 4 to index 7.
Algorithm
We use two binary searches to find the leftmost and rightmost positions ?
- First binary search finds the leftmost occurrence of the target
- Second binary search finds the rightmost occurrence of the target
- If target is not found, return [-1, -1]
Implementation
def search_range(nums, target):
def find_first():
left, right = 0, len(nums) - 1
first_pos = -1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
first_pos = mid
right = mid - 1 # Continue searching left
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return first_pos
def find_last():
left, right = 0, len(nums) - 1
last_pos = -1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
last_pos = mid
left = mid + 1 # Continue searching right
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return last_pos
first = find_first()
if first == -1:
return [-1, -1]
last = find_last()
return [first, last]
# Test the function
nums = [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6]
target = 4
result = search_range(nums, target)
print(f"Array: {nums}")
print(f"Target: {target}")
print(f"First and last position: {result}")
Array: [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6] Target: 4 First and last position: [4, 7]
Alternative Implementation Using Single Function
Here's a more compact approach that finds both positions in one function ?
def search_range_compact(nums, target):
def binary_search(find_first):
left, right = 0, len(nums) - 1
result = -1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
result = mid
if find_first:
right = mid - 1 # Search left half
else:
left = mid + 1 # Search right half
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return result
first = binary_search(True)
if first == -1:
return [-1, -1]
last = binary_search(False)
return [first, last]
# Test with different examples
test_cases = [
([2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6], 4),
([1, 2, 3, 4, 5], 3),
([1, 2, 3, 4, 5], 6),
([5, 7, 7, 8, 8, 10], 8)
]
for nums, target in test_cases:
result = search_range_compact(nums, target)
print(f"Array: {nums}, Target: {target} ? {result}")
Array: [2, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6], Target: 4 ? [4, 7] Array: [1, 2, 3, 4, 5], Target: 3 ? [2, 2] Array: [1, 2, 3, 4, 5], Target: 6 ? [-1, -1] Array: [5, 7, 7, 8, 8, 10], Target: 8 ? [3, 4]
Time and Space Complexity
- Time Complexity: O(log n) where n is the length of the array
- Space Complexity: O(1) as we only use constant extra space
Conclusion
Using binary search twice allows us to find both the first and last positions of a target element in O(log n) time. The key is to continue searching left after finding the target for the first position, and searching right for the last position.
