# LeetCode – Find First and Last Position of Element in Sorted Array (Java)

Given a sorted array of integers, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1]. For example, given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4].

Analysis

Based on the requirement of O(log n), this is a binary search problem apparently.

Java Solution 1 - Log(n)

We can first find the start and then the end of the target.

```public int[] searchRange(int[] nums, int target) { int l=0; int r=nums.length-1;   while(l<r){ int m=l+(r-l)/2; if(nums[m]<target){ l=m+1; }else{ r=m; } }   int first=l; if(l<nums.length&&nums[l]==target){//l is in boundary and is the target l=0; r=nums.length-1; while(l<r){ int m=l+(r-l+1)/2; if(nums[m]>target){ r=m-1; }else{ l=m; } }   return new int[]{first, r}; }   return new int[]{-1,-1}; }```

Java Solution 2 - (Deprecated)

```public int[] searchRange(int[] nums, int target) { if(nums == null || nums.length == 0){ return null; }   int[] arr= new int[2]; arr[0]=-1; arr[1]=-1;   binarySearch(nums, 0, nums.length-1, target, arr);   return arr; }   public void binarySearch(int[] nums, int left, int right, int target, int[] arr){ if(right<left) return;   if(nums[left]==nums[right] && nums[left]==target){ arr[0]=left; arr[1]=right; return; }   int mid = left+(right-left)/2;     if(nums[mid]<target){ binarySearch(nums, mid+1, right, target, arr); }else if(nums[mid]>target){ binarySearch(nums, left, mid-1, target, arr); }else{ arr[0]=mid; arr[1]=mid;   //handle duplicates - left int t1 = mid; while(t1 >left && nums[t1]==nums[t1-1]){ t1--; arr[0]=t1; }   //handle duplicates - right int t2 = mid; while(t2 < right&& nums[t2]==nums[t2+1]){ t2++; arr[1]=t2; } return; } }```

In the worst case, the time of the second solution is actually O(n).

Category >> Algorithms >> Interview
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• Alik Elzin

Very similar iterative solution. Added usage of “fail fast” methodology.
Recursive solution also very similar.

Iterative:
``` int[] searchRange(int[] nums, int target) { if (nums == null || nums.length == 0 || target < nums[0] || nums[nums.length-1] < target) return new int[]{-1, -1};```

``` int l = 0; int h = nums.length - 1; /* left: */ while (l < h) { int m = (l+h)/2; if (nums[m] < target) { l = m + 1; } else { h = m; { } if (l == nums.length || nums[l] != target) return int[]{-1, -1}; int left = l; h = nums.length - 1; /* Right: */ while (l < h) { int m = (l+h+1)/2; if (target < nums[m]) { h = m - 1; } else { l = m; } } ```

``` return new int[]{left, h}; } ```

Recursive:
``` // TODO: add const for `new int[]{-1, -1}` int[] searchRange(int[] nums, int target) { if (nums == null || num.length == 0) return new int[]{-1, -1};```

``` return searchRange(nums, 0, nums.length-1, int target) } int[] searchForRange(int[] nums, int from, int to, int target) { if (target < nums[from] || nums[to] < target) return new int[]{-1, -1}; if (from == to) return new int[]{from, to}; int mid = (from + to)/2; int[] rangeLower = searchForRange(nums, from, mid, target); if (rangeLower[0] != -1 && rangeLower[1] != mid) return rangeLower; int[] rangeHigher = searchRange(nums, mid+1, to, target); if (rangeHigher[0] == -1) return rangeLower; if (rangeLower[0] == -1) return rangeHigher; ```

``` return new int[]{rangeLower[0], rangeHigher[1]}; } ```

• Sumit

The solution given is O(N) and not O(logN). Consider the example {1,6,6,6,6,6,6,6,6,6,6,8}. It will have to do operations N times here.
In order to find the left and the right indices you would need to do the binary search again one for left side and other for right side of the mid if the value at mid equals the target. Below is my iterative code solution:

``` public class Solution { public int[] searchRange(int[] nums, int target) { int out[]=new int[2]; int l=0,r=nums.length-1; while(l<=r){ int mid=(l+r)/2; if(nums[mid]==target){ if(mid-1<0 || nums[mid-1]=nums.length || nums[mid+1]>target){ out[1]=mid; } else{ out[1]=rBSearch(nums,mid+1,target); } return out; } else if(nums[mid]>target){ r=mid-1; } else{ l=mid+1; } } out[0]=-1; out[1]=-1; return out; }```

``` private int lBSearch(int nums[],int end,int target){ int l=0,r=end; while(l<=r){ int mid=(l+r)/2; if(nums[mid]==target){ if(mid-1<0 || nums[mid-1]<target){ return mid; } else{ r=mid-1; } } else{ l=mid+1; } } return end; } ```

``` private int rBSearch(int nums[],int start,int target){ int l=start,r=nums.length-1; while(l=nums.length || nums[mid+1]>target){ return mid; } else{ l=mid+1; } } else{ r=mid-1; } } return start; } } ```

• lekzeey

I think the solution is fine, because the number of work required to find the left and right border using binary search is just the same as finding the element itself and scanning for the left and right borders.

• Suresh

True… I got the same doubt when I saw those two loops.

• Gdragon

Great answer! But you should make the change from right – 1 to mid – 1 in:

else if(arr[mid] > target) return solution(arr, target, left, mid-1);

• Jason Zhu

What’s wrong with the above examplary solution? The question has explicitly required the time complexity to be O(logN), which obviously is not the correct answer.

``` public static int[] solution(int[] arr, int target, int left, int right) { //parameter check if(arr == null || arr.length == 0) return new int[]{-1, -1};```

``` //boundary check if(left > right) return new int[]{-1, -1}; int mid = (left+right)/2; if(arr[mid] target) return solution(arr, target, left, right-1); else { int[] leftRange = solution(arr, target, left, mid-1); int[] rightRange = solution(arr, target, mid+1, right); int leftEnd = (leftRange[0] == -1 ? mid : leftRange[0]); int rightEnd = (rightRange[1] == -1 ? mid : rightRange[1]); return new int[]{leftEnd, rightEnd}; } } ```

```public static void main(String[] args) { System.out.println(Arrays.toString(solution(new int[]{1,8,8,8,9}, 8, 0, 4))); System.out.println(Arrays.toString(solution(new int[]{1,2,8,8,8,9}, 8, 0, 5))); System.out.println(Arrays.toString(solution(new int[]{1,2,3,8,8,8,9}, 8, 0, 6))); System.out.println(Arrays.toString(solution(new int[]{1,2,3,4,8,8,8,9}, 8, 0, 7))); System.out.println(Arrays.toString(solution(new int[]{1,2,3,4,5,8,8,9}, 8, 0, 7))); System.out.println(Arrays.toString(solution(new int[]{1,2,3,4,5,6,8,9}, 8, 0, 7))); System.out.println(Arrays.toString(solution(new int[]{1,2,3,4,8,8,8,9}, 7, 0, 7))); } ```

• Vijaya

We can use below code which has O(log N) complexity. This is initial structure, we can even modify further to clean it. (This is C# code)

public int[] searchRange(int[] nums, int target)
{
int[] result = new int[2];
int startIndex = 0;
int endIndex = nums.Length – 1;
int mid = -1;
bool foundTarget = false;

if (nums.Length > 0)
{
while (startIndex < endIndex)
{
mid = (startIndex + endIndex)/2;

if (target == nums[mid])
{
foundTarget = true;
break;
}

if (target nums[mid])
startIndex = mid+1;
}

if (foundTarget)
{
startIndex = mid;
endIndex = mid;

while ((startIndex – 1) >= 0 && (nums[startIndex – 1] == target))
startIndex–;

while ((endIndex + 1) <= nums.Length && (nums[endIndex + 1] == target))
endIndex++;

result[0] = startIndex;
result[1] = endIndex;
}
}

return result;
}

• Mark Law

this solution above time complexity is not log N, it clearly is N, which does not match the requirements.