Find the Start and End Indices of a Target in a Sorted Array
Solve this Problemnums sorted in non-decreasing order and an integer target, return the first and last index of target as a two-element array [start, end]. If target isn't present, return [-1, -1].
Solve it in O(log n) time — one binary search finds the leftmost matching index, another finds the rightmost.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 10⁴ - ◆
-10⁴ ≤ nums[i], target ≤ 10⁴ - ◆
nums is sorted in non-decreasing order (duplicates are allowed)
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int[] searchRange(int[] nums, int target) { |
| 3 | int lo = 0, hi = nums.length - 1, first = -1; |
| 4 | while (lo <= hi) { |
| 5 | int mid = lo + (hi - lo) / 2; |
| 6 | if (nums[mid] >= target) { |
| 7 | first = mid; |
| 8 | hi = mid - 1; |
| 9 | } else { |
| 10 | lo = mid + 1; |
| 11 | } |
| 12 | } |
| 13 | if (first == -1 || nums[first] != target) { |
| 14 | return new int[]{-1, -1}; |
| 15 | } |
| 16 | lo = 0; |
| 17 | hi = nums.length - 1; |
| 18 | int last = -1; |
| 19 | while (lo <= hi) { |
| 20 | int mid = lo + (hi - lo) / 2; |
| 21 | if (nums[mid] <= target) { |
| 22 | last = mid; |
| 23 | lo = mid + 1; |
| 24 | } else { |
| 25 | hi = mid - 1; |
| 26 | } |
| 27 | } |
| 28 | return new int[]{first, last}; |
| 29 | } |
| 30 | } |
| 31 |
03-1First, binary search [0, 3] for the leftmost index where nums[i] ≥ 4.
Approach & Solutions
Brute Force — Linear Scan
BruteWalk the whole array once, remembering the first index where target shows up and continuously updating the last index every time it shows up again. Correct on any array, but it never uses the fact that equal values in a sorted array are always contiguous, which is what lets binary search jump straight to both ends.
O(n)O(1)1class Solution {
2 public int[] searchRange(int[] nums, int target) {
3 int first = -1, last = -1;
4 for (int i = 0; i < nums.length; i++) {
5 if (nums[i] == target) {
6 if (first == -1) first = i;
7 last = i;
8 }
9 }
10 return new int[]{first, last};
11 }
12}Optimal — Two Binary Searches
OptimalEqual values in a sorted array sit in one contiguous block, so the answer is just its two edges. Binary-search once for the leftmost index with nums[i] ≥ target (the start, if it actually equals target), then binary-search again for the rightmost index with nums[i] ≤ target (the end).
O(log n)O(1)1class Solution {
2 public int[] searchRange(int[] nums, int target) {
3 int lo = 0, hi = nums.length - 1, first = -1;
4 while (lo <= hi) {
5 int mid = lo + (hi - lo) / 2;
6 if (nums[mid] >= target) {
7 first = mid;
8 hi = mid - 1;
9 } else {
10 lo = mid + 1;
11 }
12 }
13 if (first == -1 || nums[first] != target) {
14 return new int[]{-1, -1};
15 }
16 lo = 0;
17 hi = nums.length - 1;
18 int last = -1;
19 while (lo <= hi) {
20 int mid = lo + (hi - lo) / 2;
21 if (nums[mid] <= target) {
22 last = mid;
23 lo = mid + 1;
24 } else {
25 hi = mid - 1;
26 }
27 }
28 return new int[]{first, last};
29 }
30}