Leetcode刷题记录

96 阅读2分钟

Leetcode---34.排序数组中元素的第一个位置和最后一个位置

      因为昨天新学的二分法,所以今天决定试一下,这道题,刚开始的时候,可以看出这道题是一个递增数列,也就特别符合二分法的使用条件之一,另一个条件是没有重复元素,但是显然是有的,那么,我们怎么做比较好呢,就选择用两个二分法来找到左右边界吧

       疑问一:为什么是找到左右边界呢?

       因为是一个递增数列,如果我遍历出的左右边界一致,那么左右边界内部的数一定都相等,这也就是为什么要找左右边界。

        疑问二:左右边界怎么使用二分法啊

        下面我用图来简单说明一下这个思路过程。

        最开始是一个这样的状态,会在这个状态中找到mid,也就是中间值,(right+left)/2=2,也就是元素为6的位置,这个时候,如果我的target,也就是目标值为6的话,就已经定位到了一个值,但是此时在程序中,我们并不知道找到的这个6是否是左边界的第一个值(因为用例并不是一个确定的,在我们不清楚用例的情况下,是看不到返回的是第几个值),那么我们就需要去判断一下,它前面是否还有值或者后面是否还值(左边界值需要对前边进行判断,右边界值需要对后边进行判断),也就是用nums[mid] !=nums[mid-1]来做判断。

2023-07-05-14-45-26-image.png         左边界:若已经是第一个值,那么直接返回,当作左边界值即可,若不是第一个值,假设如下图

2023-07-05-14-56-16-image.png

那么我们要得到左边界,就需要将right左移,不断地缩小区间,也就是right=mid-1,这样的话,直接就将后边的重复值忽略掉了。

2023-07-05-14-56-44-image.png

具体代码如下:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int first = searchFirst(nums,target);
        int last = searchLast(nums,target);
        return new int[]{first,last};
    }
    public int searchFirst(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){
                right = mid-1;
            }else if(nums[mid]<target){
                left = mid+1; 
            }else{
                if(mid == 0 || nums[mid] != nums[mid-1]){
                    return mid;
                }else{
                    right = mid-1;
                }
            } 
        }
        return -1;
    }
    public int searchLast(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){
                right = mid-1;
            }else if(nums[mid]<target){
                left = mid+1; 
            }else{
                if(mid ==  nums.length-1|| nums[mid] != nums[mid+1]){
                    return mid;
                }else{
                    left = mid+1;
                }
            } 
        }
        return -1;
    }
}

(本文的思路出处:二分法的思想来自于代码随想录的carl哥,这道题的解题思想来自于b站的忍者算法,我只是将一些,我当时思考有问题的地方,复现了出来)