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
-10^9Â <= nums[i]Â <= 10^9
nums
 is a non-decreasing array.
-10^9 <= target <= 10^9
1. Iterative Solution
class Solution {
// Method to find the starting position of the target
//If found in middle, keep the search continued to find if the same element exist on the LEFT of sorted array
private int findLowerBound ( int [] nums , int target ) {
int start = 0 , end = nums.length - 1 ;
int lowerBound = - 1 ;
while (start <= end) {
int mid = start + (end - start) / 2 ;
if (nums[mid] == target) {
lowerBound = mid;
end = mid - 1 ; // Narrow down to the left half
} else if (target < nums[mid]) {
end = mid - 1 ;
} else {
start = mid + 1 ;
}
}
return lowerBound;
}
// Method to find the ending position of the target
//If found in middle, keep the search continued to find if the same element exist on the RIGHT of sorted array.
private static int findUpperBound ( int [] nums , int target ) {
// Handle the case for an empty array
if (nums.length == 0 ) return - 1 ;
int start = 0 , end = nums.length;
// Binary search loop
while (start < end) {
int mid = start + (end - start) / 2 ;
if (nums[mid] > target) {
end = mid; // Narrow down to the left half
} else {
start = mid + 1 ; // Narrow down to the right half
}
}
// Check if the element before 'start' is the target
if (start - 1 >= 0 && nums[start - 1 ] != target) return - 1 ;
// Return the index of the upper bound
return start - 1 ;
}
// Main method to find the starting and ending position of the target
public int [] searchRange ( int [] nums , int target ) {
int [] res = new int [ 2 ];
res[ 0 ] = findLowerBound (nums, target);
res[ 1 ] = findUpperBound (nums, target);
return res;
}
}
2. Recursive Solution”
class Solution {
// Method to find the starting position of the target
private int findLowerBoundUtil ( int [] nums , int target , int start , int end ) {
if (start > end) {
return - 1 ;
}
int mid = start + (end - start) / 2 ;
int lowerBound = - 1 ;
if (nums[mid] == target) {
int leftRes = findLowerBoundUtil (nums, target, start, mid - 1 );
lowerBound = leftRes != - 1 ? leftRes : mid;
} else if (target < nums[mid]) {
lowerBound = findLowerBoundUtil (nums, target, start, mid - 1 );
} else {
lowerBound = findLowerBoundUtil (nums, target, mid + 1 , end);
}
return lowerBound;
}
// Method to find the ending position of the target
private int findUpperBoundUtil ( int [] nums , int target , int start , int end ) {
if (start > end) {
return - 1 ;
}
int mid = start + (end - start) / 2 ;
int upperBound = - 1 ;
if (nums[mid] == target) {
int rightRes = findUpperBoundUtil (nums, target, mid + 1 , end);
upperBound = rightRes != - 1 ? rightRes : mid;
} else if (target < nums[mid]) {
upperBound = findUpperBoundUtil (nums, target, start, mid - 1 );
} else {
upperBound = findUpperBoundUtil (nums, target, mid + 1 , end);
}
return upperBound;
}
// Main method to find the starting and ending position of the target
public int [] searchRange ( int [] nums , int target ) {
int [] res = new int [ 2 ];
res[ 0 ] = findLowerBoundUtil (nums, target, 0 , nums.length - 1 );
res[ 1 ] = findUpperBoundUtil (nums, target, 0 , nums.length - 1 );
return res;
}
}