leetcode记录-34-在排序数组中查找元素出现的第一个和最后一个位置-二分经典

这篇博客介绍了如何使用二分查找法在排序数组中找到目标元素出现的第一个和最后一个位置。首先寻找左边界,当找到目标元素时,继续检查其左侧是否存在相同元素,然后寻找右边界,检查右侧。文章强调了二分查找的细节,包括区间的选择、退出循环的条件以及防止死循环。最后提供了通用的二分查找模板和总结。
摘要由CSDN通过智能技术生成

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

在这里插入图片描述

思路

如果直接用二分法寻找区间比较困难,当找到target时又要向左又要向右不知道该如何处理 —— 问题转化为寻找target出现的第一个位置(左边界)和寻找target出现的最后一个位置(右边界)两个二分,在每次二分中,注意l和r的初始条件,while的条件,l和r如何变化(自己习惯左闭右闭的写法),在寻找左边界时,mid大于和小于的情况正常r=mid-1l=mid+1,但是当找到target的下标index,需要看左边是否还有,所以要让r=mid-1,如果左边没有,那最终会在处理index-1处的元素,因为此时该元素小于target需要让l=(index-1)+1=index,但是r=index-1,所以退出循环,此时l就是左边界。但是还有种情况,当所有的都比target小,寻找左边界就会一直加到nums.length,当不存在但是大小位于区间中部或者所有的比target大,结束时l为中间的某下标0下标,这两个下标虽然存在数但是却不等于target——结束时这几种都要判断,直接返回[-1,-1]。右边界同理。

代码

class Solution {
    public int[] searchRange(int[] nums, int target) {
        if (nums.length==0) return new int[]{-1,-1};
        int l=0,r=nums.length-1;
        int[] res={-1,-1};
        //寻找左边界
        while(l<=r){
            int mid= l+(r-l)/2;
            if (nums[mid]<target) l=mid+1;
            else if (nums[mid]>target) r=mid-1;
            else if (nums[mid]==target) r=mid-1; //需要查找前面的区间是否还有,如果没有最后l=r+1为当前mid
        }
        if (l> nums.length-1||nums[l]!=target)
            return res;
        res[0]=l;
        //寻找右边界
        l=0;
        r=nums.length-1;
        while(l<=r){
            int mid= l+(r-l)/2;
            if (nums[mid]<target) l=mid+1;
            else if (nums[mid]>target) r=mid-1;
            else if (nums[mid]==target) l=mid+1; //需要查找后面的区间是否还有,如果没有最后r=l-1(l=r+1)为当前mid
        }
        if (r<0||nums[r]!=target)
            return new int[]{-1,-1};
        res[1]=r;
        return res;
    }
}

技巧和总结

  1. ①使用二分尽量习惯性的选择左闭右闭的写法或者左闭右开的写法任一种,保持。
    ②而且要思考区间剩最后一两个元素是否会陷入死循环。
    ③还要思考退出循环条件。
  2. 左闭右闭的写法模板(标*的为左闭右闭和左闭右开的区别):
int binarySearch(int[] nums, int target) {
    int left = 0; 
    int right = nums.length - 1; //**************************

    while(left <= right) { //********************
        int mid = left + (right - left) / 2;
        if(nums[mid] == target)
            return ------; //不同需求不同**************
        else if (nums[mid] < target)
            left = mid + 1; // ***************************
        else if (nums[mid] > target)
            right = mid - 1; // ************************
    }
    return -1;//不同需求不同
}
  1. 具体的二分通用思路,以及各种写法的区别和各种细节参考:labuladong的题解:二分查找细节详解,顺便赋诗一首
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值