每日一题 — 在排序数组中查找元素的第一个和最后一个位置

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

 思路:当查找该元素的最左侧位置时,如下图:

我们首先需要判断情况:

  • 当mid < target 的时候:mid在左边这个区间里面,无法求出结果,所以让left右移,   left = mid+1;
  • 当mid >= target 的时候:mid在右边这个区间里面,mid也有可能刚好等于target,我们得缩小范围,所以  right = mid(不能等于mid-1,否则如果mid刚好等于target的时候,right = mid-1 之后,就无解了);

细节处理:

  1. 循环条件选择:
    left < right
    left <= right

    在求最左侧端点的时候,我们采用第一种循环条件,如果使用第二种循环条件,会导致死循环

  2. mid有两种求法:
    mid = left +(right - left)/ 2  — 求出的值会偏左
    mid = left +(right - left + 1)/ 2  —求出的值会偏右
    在求最左侧位置的时候,只能使用第一种方法,因为使用第二种方法会导致死循环

    当只剩下两个数判断且 mid = target 的时候,此时如果right = mid,这个两个数的的mid一直等于right,而right又等于 mid,陷入死循环

 






同理当查找该元素的最右侧位置时,如下图:

我们首先需要判断情况:

  • 当mid <= target 的时候:mid在左边这个区间里面,mid可能刚好等于target,所以让left右移的时候需要注意不能加一,否则会导致无解,left = mid;
  • 当mid > target 的时候:mid在右边这个区间里面,无法求出结果,我们得缩小范围,所以 right = mid-1;

细节处理:

  1.  循环条件选择:
    left < right
    left <= right

    在求最左侧端点的时候,我们采用第一种循环条件,如果使用第二种循环条件,会导致死循环

  2. mid有两种求法:
    mid = left +(right - left)/ 2  — 求出的值会偏左
    mid = left +(right - left + 1)/ 2  —求出的值会偏右
    在求最左侧位置的时候,只能使用第二种方法,因为使用第一种方法会导致死循环

    当只剩下两个数判断且 mid = target 的时候,此时如果left = mid,这个两个数的的mid一直等于left,而left又等于 mid,陷入死循环

代码:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] ret = new int[2];
        ret[0] = -1;
        ret[1] = -1;
        if(nums.length == 0){
            return ret;
        }
        int left = 0;
        int right = nums.length - 1;
        //判断左端点
        while(left < right){
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
                left = mid+1;
            }else{
                right = mid;
            }
        }
        //判断是否等于目标值
        if(nums[left] != target){
            return ret;
        }else{
            ret[0] = left;
        }
        left = 0;
        right = nums.length - 1;
        //判断右端点
        while(left < right){
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] <= target){
                left = mid;
            }else{
                right = mid-1;
            }
        }
        //判断是否等于目标值
        if(nums[left] != target){
            return ret;
        }else{
            ret[1] = left;
        }
        return ret;
    }
}

总结模板:

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值