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

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

题例

示例1

输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]

示例2

输入:nums = [5,7,7,8,8,10], target = 6 输出:[-1,-1]

示例3

输入:nums = [], target = 0 输出:[-1,-1]

分析

题目给的整数数组是一个升序排列的数组,排序数组查找元素,我们采用二分查找法进行查找。通过不断的缩小区间,最后定位到该元素可能存在的区间,再判断其是否存在,返回我们的结果。

实现

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if(nums.length==0) return new int[]{-1,-1};
        int left = searchLeft(0,nums.length-1,nums,target);
        int right = searchRight(0,nums.length-1,nums,target);
        return new int[]{left,right};
    }
    private int searchLeft(int left,int right,int[] nums,int target){
        while(left<right){
            int mid = (left+right)>>>1;
            if(nums[mid]<target) left=mid+1;
            else right = mid;
        }
        return nums[left]==target?left:-1;
    }
    private int searchRight(int left,int right,int[] nums,int target){
        while(left<right){
            int mid = (left+right+1)>>>1;
            if(nums[mid]>target) right = mid-1;
            else left = mid;
        }
        return nums[left]==target?left:-1;
    }
}

说明

首先判断数组是否为空,如果是空数组就直接返回[-1,-1]了

if(nums.length==0) return new int[]{-1,-1};

题目的要求是返回目标值在数组中的开始位置和结束位置,我们分开做处理。 左边的采用下取整,逐渐缩小左边的区间范围。

private int searchLeft(int left,int right,int[] nums,int target){
        while(left<right){
            int mid = (left+right)>>>1;
            if(nums[mid]<target) left=mid+1;
            else right = mid;
        }
        return nums[left]==target?left:-1;
    }

右边的采用上取值,逐渐缩小右边的区间范围。

private int searchRight(int left,int right,int[] nums,int target){
        while(left<right){
            int mid = (left+right+1)>>>1;
            if(nums[mid]>target) right = mid-1;
            else left = mid;
        }
        return nums[left]==target?left:-1;
    }

上取值和下取整的不同之处就在于这两段代码。

int mid = (left+right)>>>1;
int mid = (left+right+1)>>>1;

>>>1>>1的区别以及上取值和下取整的使用在二分查找中也有讲过,有兴趣的朋友可以去看一看。


每个不起眼的日子,都是反败为胜的资本