LeetCode34. 在排序数组中查找元素范围 | 刷题打卡

267 阅读2分钟

LeetCode从低效到高效,点击

一、题目描述:

题目要求

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

来源:力扣(LeetCode)链接

示例

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

二、思路分析:

本题是一道经典的二分查找题目,是普通二分查找的变形,搜索指定元素的边界,搜索有没有元素就是简单的二分查找,查找搜算范围我最开始想到的思路就是找到指定元素,然后从左找到一个不是这个元素的位置,再去找右边,但是如果这样去搜所的话如果被查找元素的数量很多,那这个算法效率就差不多是O(n)O(n),所以即使找到了指定元素也应该继续使用二分的策略。 搜索左边界时,如果发现元素,右指针要压过来,使搜索范围尽可能向左找,不用担心最后左指针找不到目标元素,因为这个搜索没有异常退出,所以左指针是必定大于右指针的

三、AC 代码:

先搜左边界,再搜右边界 这个版本更好理解

// 8 ms 13.4 MB
vector<int> searchRange_v1(const vector<int>& nums, int target) {
    int l=0,r=nums.size()-1;
    int mid;
    while(l<=r){
        mid = (l+r)>>1;
        // 搜索左边界就是找到目标点时把右指针指过去,因为这个结构没有return出口,所以left一定会大于right指向tar,除非不存在tar
        if(nums[mid]==target){
            r = mid -1;
        }else if (nums[mid]>target)
        {
            r = mid -1;
        }else{
            l = mid + 1;
        }
    }
    // 注意这个顺序不能搞错,要先判断位置对不对,然后才能检查这个位置存的对不对。如果找不到左边界,那也不用搜索右边界
    if(l>=nums.size()||nums[l]!=target)
        return {-1,-1};
    int tarleft = l;
    // 搜索右端点
    l=0,r=nums.size()-1;
    while(l<=r){
        mid = (l+r)>>1;
        if(nums[mid]==target){
            l = mid + 1;
        }else if (nums[mid]>target)
        {
            r = mid - 1;
        }else{
            l = mid + 1;
        }
    }
    return {tarleft,r};
}

压缩判断条件

// 8 ms 13.1 MB
vector<int> searchRange(const vector<int>& nums, int target) {
    int l=0,r=nums.size()-1;
    int mid;
    while(l<=r){
        mid = (l+r)>>1;
        if(nums[mid]<target){
            l = mid + 1;
        }else{
            r = mid -1;
        }
    }
    if(l>=nums.size()||nums[l]!=target)
        return {-1,-1};
    int tarleft = l;
    l=0,r=nums.size()-1;
    while(l<=r){
        mid = (l+r)>>1;
        if (nums[mid]>target)
        {
            r = mid - 1;
        }else{
            l = mid + 1;
        }
    }
    return {tarleft,r};
}

四、总结:

搜索元素范围是一道二分查找的魔改题目,程序的主题框架并没有改变,我更习惯二分查找使用左闭右闭的搜索范围,如果习惯左闭右开也都可以

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情