LeetCode 热题100-18-在排序数组中查找元素的第一个和最后一个位置

核心思想:二分查找
二分模板:
模板一将区间划分为[l,mid]和[mid+1,r],计算mid时不需要加1,即mid = (l + r)/2。

//模板一
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = (l + r)/2;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

模板二将区间划分为[l,mid-1]和[mid,r],此时为了防止死循环,计算mid时需要加1,即mid = (l + r)/2。

//模板二
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = ( l + r + 1 ) /2;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

口诀:mid+1不加1,mid-1需加1。
本题为什么要取左边第一个用模板一,而取最后一个用模板二?
答:取左边第一个target时,当nums[mid]==target时,中间位置的右边元素一定不是target出现的第一个位置,所以下次搜索区间是[l,r],r=mid;取最后一个target时,当nums[mid]==target时,中间位置的左边元素一定不是target出现的最后一个位置,所以下次搜索区间是[l,r],l=mid;

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int l = 0;
        int r = nums.length - 1;
        int mid;
        if(r == -1){
            return new int[]{-1,-1};
        }
        //寻找左边界
        while(l < r){
            mid = (l + r) / 2;
            if(nums[mid] >= target){
                r = mid;	//寻找左边界,就要在nums[middle] == target的时候更新r
            }else{
                l = mid + 1;
            }
        }
        if(nums[l] != target){
            return new int[]{-1,-1};
        }
        int L = l;
        l = 0; 
        r = nums.length - 1;
        //寻找右边界
        while(l < r){
            mid = (l + r + 1) / 2; 
            if(nums[mid] <= target){
                l = mid;	//寻找右边界,就要在nums[middle] == target的时候更新l
            }else{
                r = mid - 1;
            }
        }
        return new int[]{L,r};
    }
}

你可能感兴趣的:(Leetcode热题100,leetcode,算法,排序算法)