二分搜索-在排序数组中查找元素的第一个和最后一个位置

67 阅读2分钟

34. 在排序数组中查找元素的第一个和最后一个位置

描述

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

分析

对比之前的二分搜索,找到对应target就返回结果。这道题的要求更进一步,给定数组中寻找的target可能存在多个,要求找到其左右区间之后再返回。

思路

改进之处:分别寻找左右边界

  • 利用二分法寻找左边界:往左区间寻找时(right=mid-1;),若找到了对应的target元素,可以用变量leftBound做个记录,然后跳过该元素继续往左区间寻找;往右区间寻找时,逻辑相同。
  • 利用二分法寻找右边界:往右区间寻找时(left=mid+1;),若找到了对应的target元素,可以用变量rightBound做个记录,然后跳过该元素继续往左区间寻找;往左区间寻找时,逻辑相同。
  • 最后返回左右边界即可

代码

寻找左边界

 public int getLeftBound(int[] nums, int target){
        int left=0;
        int right=nums.length-1;
        int mid;
        int leftBound=-1;
        while(left<=right){
             mid=(left+right)/2;
            if(nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
                leftBound=mid;
            }

        }

        if(leftBound!=-1&&nums[leftBound]==target){
            return leftBound;
        }
        return -1;

    }

寻找右边界

 public int getRightBound(int[] nums, int target){
        int left=0;
        int right=nums.length-1;
        int mid;
        int rightBound=-1;
        while(left<=right){
             mid=(left+right)/2;
            if(nums[mid]>target){
                 right=mid-1;
            }else{
                left=mid+1;
                rightBound=mid;
            }

        }

        if(rightBound!=-1&&nums[rightBound]==target){
            return rightBound;
        }
        return -1;
    }

最终代码

    public int[] searchRange(int[] nums, int target) {
        int left=getLeftBound(nums,target);
        int right=getRightBound(nums,target);

        return new int[]{left,right};

    }