Find First and Last Position of Element in Sorted Array


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]

This algorithm finds the starting and ending positions of a target value in a sorted array by performing two specialized binary searches:

  1. Finding the First Occurrence:
    • A binary search is used to locate the target.
    • When an instance of the target is found at an index mid, it’s a potential first occurrence. We record this index and then continue searching only in the left half (i.e., elements before mid). This ensures we find the leftmost (first) instance. If no target is found, this search returns -1.
  2. Finding the Last Occurrence:
    • A separate binary search is performed.
    • When an instance of the target is found at mid, it’s a potential last occurrence. We record this index and then continue searching only in the right half (i.e., elements after mid). This ensures we find the rightmost (last) instance. If no target is found, this search returns -1.
  3. Result:
    • The results from these two searches give the start and end indices of the target’s range. If the target isn’t found by either (or specifically, if the first search fails, the target isn’t present), the range is [-1, -1].

This approach is efficient because each binary search takes logarithmic time (O(log n)), making the overall algorithm run in O(log n) time.

class Solution {

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

        int firstOccurrence = findFirst(nums, target);
        int lastOccurrence = findLast(nums, target);

        return new int[]{firstOccurrence, lastOccurrence};
    }

    // Helper function to find the first occurrence of the target
    private int findFirst(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        int first = -1;

        while (low <= high) {
            int mid = low + (high - low) / 2; // Prevents potential overflow

            if (nums[mid] == target) {
                first = mid;       // Found a target, this could be the first one
                high = mid - 1;    // Try to find an earlier one in the left subarray
            } else if (nums[mid] < target) {
                low = mid + 1;     // Target is in the right subarray
            } else { // nums[mid] > target
                high = mid - 1;    // Target is in the left subarray
            }
        }
        return first;
    }

    // Helper function to find the last occurrence of the target
    private int findLast(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        int last = -1;

        while (low <= high) {
            int mid = low + (high - low) / 2; // Prevents potential overflow

            if (nums[mid] == target) {
                last = mid;        // Found a target, this could be the last one
                low = mid + 1;     // Try to find a later one in the right subarray
            } else if (nums[mid] < target) {
                low = mid + 1;     // Target is in the right subarray
            } else { // nums[mid] > target
                high = mid - 1;    // Target is in the left subarray
            }
        }
        return last;
    }
}


Leave a comment