#34 Find First and Last Position of Element in Sorted Array
frequently reported atMetaLinkedInAppleBloombergAmazonMicrosoft
the problem
In plain words
Given a sorted array (duplicates allowed), return [first, last] index of target, or [-1, -1] if absent. Must be O(log n).
in nums = [5,7,7,8,8,10], target = 8
out [3,4]
in nums = [5,7,7,8,8,10], target = 6
out [-1,-1]
in nums = [], target = 0
out [-1,-1]
- 0 ≤ n ≤ 10⁵
- -10⁹ ≤ nums[i], target ≤ 10⁹
- Sorted non-decreasing
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternBinary search (exact & bounds)
first = lower bound (first ≥ target); last = upper bound (first > target) minus one. Two O(log n) searches, no scanning across the run of duplicates.
solutions
From brute force to optimal
Record the first and last index where nums[i] == target.
- Scan all i.
- Set first on the first hit, update last on every hit.
Visits every element.
Two indices.
class Solution { public int[] searchRange(int[] nums, int target) { int first = -1, last = -1; for (int i = 0; i < nums.length; i++) { if (nums[i] == target) { if (first == -1) first = i; last = i; } } return new int[] {first, last}; }}On a hit, remember it and keep searching left (for first) or right (for last).
- Run lo ≤ hi search twice.
- On equality: ans = mid; then hi = mid − 1 (leftmost) or lo = mid + 1 (rightmost).
Two full binary searches.
A few integers.
class Solution { public int[] searchRange(int[] nums, int target) { return new int[] {find(nums, target, true), find(nums, target, false)}; } /** Classic lo <= hi search that keeps going after a hit, leaning left or right. */ private int find(int[] nums, int target, boolean leftmost) { int lo = 0, hi = nums.length - 1, ans = -1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] == target) { ans = mid; // remember it, keep searching if (leftmost) hi = mid - 1; else lo = mid + 1; } else if (nums[mid] < target) { lo = mid + 1; } else { hi = mid - 1; } } return ans; }}Two boundary searches with the lo < hi template; no special case for the hit.
- first = lowerBound(target).
- If first == n or nums[first] ≠ target → [-1, -1].
- last = upperBound(target) − 1.
Two binary searches of log n each.
A few integers.
class Solution { public int[] searchRange(int[] nums, int target) { int first = lowerBound(nums, target); // first index with value >= target if (first == nums.length || nums[first] != target) return new int[] {-1, -1}; int last = upperBound(nums, target) - 1; // (first index with value > target) - 1 return new int[] {first, last}; } private int lowerBound(int[] a, int t) { int lo = 0, hi = a.length; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (a[mid] >= t) hi = mid; // mid could be the first copy: keep it else lo = mid + 1; // too small: drop mid and everything left of it } return lo; } private int upperBound(int[] a, int t) { int lo = 0, hi = a.length; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (a[mid] > t) hi = mid; // bigger than t: the boundary is mid or left of it else lo = mid + 1; // <= t (copies too): the boundary is right of mid } return lo; }}Dry run
in the room
How to say it in the interview
talk track
- Mention the trap first: "find any 8 then expand both ways" is O(n) when the array is all 8s.
- Present lower/upper bound as reusable helpers — clean code scores points.
traps
- Expanding outward from one match: correct but O(n) worst case.
- Forgetting the
first == ncheck before readingnums[first].
what they ask next
Follow-ups
How many times does target occur?
upperBound − lowerBound, in O(log n).
before you submit
Edge cases to test
- Empty array → [-1, -1].
- Every element is the target: [2, 2, 2, 2] → [0, 3] — a walk from one hit would be O(n).
- Target missing but between two values: lower bound lands on a different value, so check nums[first] == target.
practise next
Similar problems
- #35Search Insert PositionEasyin Binary Search
- #278First Bad VersionEasyin Binary Search