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.
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6 Output: [-1,-1]
Example 3:
Input: nums = [], target = 0 Output: [-1,-1]
Constraints:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums
is a non-decreasing array.-109 <= target <= 109
Companies: Facebook, Adobe, Amazon, Google, Apple, Bloomberg, Oracle, Microsoft, LinkedIn, Uber, Intuit, Qualtrics, Yahoo, Nutanix, TikTok, instacart, SAP, Samsung
Related Topics:
Array, Binary Search
Similar Questions:
- First Bad Version (Easy)
- Plates Between Candles (Medium)
- Find Target Indices After Sorting Array (Easy)
Pro:
M
is always(L + R) / 2
- Symmetrical and no-brainer:
L = M + 1
andR = M - 1
.
Con:
L
andR
might go out of boundary.
Solution: Simply do a out-of-boundary check.- Need to think about using
L
orR
in the end.
Solution: Take the first binary search for example, ifA[M] < target
, we moveL
. IfA[M] >= target
, we moveR
. In the end,L
andR
will swap order, soR
will point to the lastA[i] < target
, andL
will point to the firstA[i] >= target
. Thus, we should useL
as the left boundary.
// OJ: https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
// Author: github.com/lzl124631x
// Time: O(logN)
// Space: O(1)
class Solution {
public:
vector<int> searchRange(vector<int>& A, int target) {
int N = A.size(), L = 0, R = N - 1;
while (L <= R) {
int M = (L + R) / 2;
if (A[M] < target) L = M + 1;
else R = M - 1;
}
if (L == N || A[L] != target) return {-1,-1};
int left = L;
R = N - 1;
while (L <= R) {
int M = (L + R) / 2;
if (A[M] > target) R = M - 1;
else L = M + 1;
}
return {left, R};
}
};
Pro:
- In the end,
L
andR
points to the same position.
Con:
- Need to think about setting
L = M
orR = M
. Solution: Take the first binary search for example. IfA[M] < target
, we want to moveL
toM + 1
becauseA[M] != target
. IfA[M] >= target
, we want to moveR
toM
. Since we are usingR = M
, we need to make sureM != R
, thus we should round downM
as(L + R) / 2
.
Now consider the second binary search. If A[M] > target
, we want to move R
to M - 1
. If A[M] <= target
, we want to move L
to M
. Since we are using L = M
, we need to make sure M != R
, thus we should round up M
as (L + R + 1) / 2
.
Overall, if we do L = M
, we round up. If we do R = M
, we round down.
Round up: (L + R) / 2
or L + (R - L) / 2
.
Round down: (L + R + 1) / 2
or R - (R - L) / 2
.
// OJ: https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
// Author: github.com/lzl124631x
// Time: O(logN)
// Space: O(1)
class Solution {
public:
vector<int> searchRange(vector<int>& A, int target) {
if (A.empty()) return {-1,-1};
int N = A.size(), L = 0, R = N - 1;
while (L < R) {
int M = (L + R) / 2;
if (A[M] < target) L = M + 1;
else R = M;
}
if (A[L] != target) return {-1,-1};
int left = L;
L = 0, R = N - 1;
while (L < R) {
int M = (L + R + 1) / 2;
if (A[M] > target) R = M - 1;
else L = M;
}
return {left, L};
}
};