[Medium] 34. Find First and Last Position of Element in Sorted Array
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.
Examples
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Explanation: The target value 8 appears at indices 3 and 4.
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
Explanation: The target value 6 is not found in the array.
Example 3:
Input: nums = [], target = 0
Output: [-1,-1]
Explanation: The array is empty, so target is not found.
Constraints
0 <= nums.length <= 10^5-10^9 <= nums[i] <= 10^9numsis a non-decreasing array.-10^9 <= target <= 10^9
Thinking Process
- Lower Bound vs Upper Bound: Understanding the difference between lower bound (first position >= target) and upper bound (first position > target) is crucial
- The search space must shrink monotonically each step.
- Decide which half still satisfies the predicate, discard the other.
- Use
mid = left + (right - left) / 2to avoid overflow.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Standard binary search | O(log n) | O(1) | Sorted array, left <= right |
| Lower / upper bound | O(log n) | O(1) | First/last position, insert index |
| Binary search on rotated array (this problem) | O(log n) | O(1) | Identify sorted half, discard other |
| Binary search on answer | O(n log M) | O(1) | Monotonic predicate over search space |
Solution
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.empty()) return {-1, -1};
int left = lowerBound(nums, target);
if (left == nums.size() || nums[left] != target) {
return {-1, -1};
}
int right = upperBound(nums, target) - 1;
return {left, right};
}
private:
int lowerBound(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] < target) left = mid + 1;
else right = mid;
}
return left;
}
int upperBound(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] <= target) left = mid + 1;
else right = mid;
}
return left;
}
};
Solution Explanation
Approach: Binary search on rotated array (this problem)
Key idea: 1. Lower Bound vs Upper Bound: Understanding the difference between lower bound (first position >= target) and upper bound (first position > target) is crucial
How the code works:
- Lower Bound vs Upper Bound: Understanding the difference between lower bound (first position >= target) and upper bound (first position > target) is crucial
- The search space must shrink monotonically each step.
- Decide which half still satisfies the predicate, discard the other.
- Use
mid = left + (right - left) / 2to avoid overflow.
Walkthrough — input nums = [5,7,7,8,8,10], target = 8, expected output [3,4]:
The target value 8 appears at indices 3 and 4.
- Time Complexity: O(log n) - Two binary searches, each taking O(log n) time
- Space Complexity: O(1) - Only using a constant amount of extra space
Related Problems
- 35. Search Insert Position - Find insertion position (lower bound)
- 704. Binary Search - Standard binary search
- 33. Search in Rotated Sorted Array - Binary search on rotated array
- 162. Find Peak Element - Binary search variant
Common Mistakes
- Skipping edge cases (empty input, single element, boundaries).
- Off-by-one errors in loops and index ranges.
- Forgetting to handle the case when no valid answer exists.
Key Takeaways
- Lower Bound vs Upper Bound: Understanding the difference between lower bound (first position >= target) and upper bound (first position > target) is crucial
- Binary Search Variants: This problem demonstrates two important binary search variants that are commonly used
- Boundary Conditions: Careful handling of edge cases (empty array, target not found) is essential
- Range Calculation: Upper bound minus 1 gives the last occurrence when target exists
References
- LC 34: Find First and Last Position of Element in Sorted Array on LeetCode
- LeetCode Discuss — LC 34: Find First and Last Position of Element in Sorted Array
- LeetCode Editorial (may require premium)