LeetCode – Search for a Range (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

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;
    }
}
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>
  • 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.