34. Find First and Last Position of Element in Sorted Array - Detailed Explanation
Problem Statement
You are given an array of integers nums sorted in non-decreasing order and a target value target. Your task is to find the starting and ending position of the given target in the array. If the target is not present, return [-1, -1].
Example Inputs, Outputs, and Explanations
-
Example 1
- Input:
nums = [5,7,7,8,8,10],target = 8 - Output:
[3,4] - Explanation: The target value
8appears at indices3and4.
- Input:
-
Example 2
- Input:
nums = [5,7,7,8,8,10],target = 6 - Output:
[-1,-1] - Explanation: The target value
6is not present in the array.
- Input:
-
Example 3
- Input:
nums = [],target = 0 - Output:
[-1,-1] - Explanation: The array is empty, so the target cannot be found.
- Input:
Constraints
- The array nums is sorted in non-decreasing order.
- The length of nums is between
0and10^5. - Each element in nums is an integer.
- The target is an integer.
Hints
-
Hint 1:
Since the array is sorted, think about using binary search to find the target. A standard binary search finds one occurrence, but you need to find the boundaries (first and last positions). -
Hint 2:
Modify binary search to find the left boundary (first occurrence) and then separately find the right boundary (last occurrence). Focus on moving the search boundaries even when you find the target.
Approaches to Solve the Problem
Approach 1: Brute Force (Linear Scan)
Idea
- Traverse the array from start to end.
- Record the first and last positions when you encounter the target.
Steps
- Initialize
firstto-1andlastto-1. - Iterate over the array:
- When you see the target for the first time, update
first. - Keep updating
lastwhenever you see the target.
- When you see the target for the first time, update
- Return
[first, last].
Drawbacks
- Time Complexity: O(n) – acceptable for small arrays but not optimal for large arrays.
Approach 2: Optimal Binary Search
Idea
- Use binary search twice:
- Left Boundary Search: Find the first occurrence by moving the high pointer even if you find the target.
- Right Boundary Search: Find the last occurrence by moving the low pointer even if you find the target.
Detailed Steps
- Find Left Boundary:
- Initialize
leftto0andrightton - 1. - While
left <= right:- Compute
mid = (left + right) // 2. - If
nums[mid]is less than the target, movelefttomid + 1. - Otherwise, move
righttomid - 1.
- Compute
- After the loop,
leftshould point to the first occurrence if it exists.
- Initialize
- Find Right Boundary:
- Reinitialize
leftto0andrightton - 1. - While
left <= right:- Compute
mid = (left + right) // 2. - If
nums[mid]is greater than the target, moverighttomid - 1. - Otherwise, move
lefttomid + 1.
- Compute
- After the loop,
rightshould point to the last occurrence if it exists.
- Reinitialize
- Validation:
- Verify that the found positions are within array bounds and that the target is indeed present.
Advantages
- Time Complexity: O(log n) for each binary search, so overall O(log n).
- Space Complexity: O(1).
Step-by-Step Walkthrough with Visual Example
Consider nums = [5, 7, 7, 8, 8, 10] and target = 8.
Finding the Left Boundary:
- Initial:
left = 0,right = 5
Computemid = (0 + 5) // 2 = 2→nums[2] = 7
Since7 < 8, updateleft = mid + 1 = 3. - Next:
left = 3,right = 5
Computemid = (3 + 5) // 2 = 4→nums[4] = 8
Since8is equal to target, moveright = mid - 1 = 3to search further left. - Next:
left = 3,right = 3
Computemid = (3 + 3) // 2 = 3→nums[3] = 8
Since8is equal to target, updateright = mid - 1 = 2. - Termination:
left = 3,right = 2
The left boundary is at index3.
Finding the Right Boundary:
- Initial:
left = 0,right = 5
Computemid = (0 + 5) // 2 = 2→nums[2] = 7
Since7 < 8, updateleft = mid + 1 = 3. - Next:
left = 3,right = 5
Computemid = (3 + 5) // 2 = 4→nums[4] = 8
Since8equals target, updateleft = mid + 1 = 5to search further right. - Next:
left = 5,right = 5
Computemid = (5 + 5) // 2 = 5→nums[5] = 10
Since10 > 8, updateright = mid - 1 = 4. - Termination:
left = 5,right = 4
The right boundary is at index4.
Final result is [3, 4].
Code Implementation
Python Implementation
Java Implementation
Complexity Analysis
-
Brute Force Approach:
- Time Complexity: O(n) – the array is scanned once.
- Space Complexity: O(1) – only a few variables are used.
-
Optimal Binary Search Approach:
- Time Complexity: O(log n) – two binary search passes.
- Space Complexity: O(1) – no extra space apart from variables.
Common Mistakes & Edge Cases
Common Mistakes
- Not checking boundaries:
Make sure that the returned index is within the bounds of the array and that the target is actually present. - Infinite Loops:
Carefully adjust theleftandrightpointers to ensure that the loop terminates. - Off-by-One Errors:
Adjust the binary search conditions properly when moving the pointers.
Edge Cases
- Empty Array:
Return[-1, -1]whennumsis empty. - Target Not Present:
Always verify the target’s existence after the binary search. - Array with One Element:
Properly handle the scenario when the array has only one element.
Alternative Variations and Related Problems
Alternative Problem Variations
- Count of Target Occurrences:
Instead of returning the positions, return the count of the target’s occurrences. - First and Last Occurrence in Unsorted Array:
Adapt the problem to work on an unsorted array (typically with a linear scan).
Related Problems for Further Practice
- Binary Search Problems:
Practice various binary search problems to get comfortable with modifying the algorithm for boundaries. - Search Insert Position:
Find the index where a target should be inserted in a sorted array. - Find Peak Element:
Locate a peak element in an array using binary search. - Search in Rotated Sorted Array:
Use modified binary search to find an element in a rotated sorted array.
GET YOUR FREE
Coding Questions Catalog
$197

$78
$78