在做题中学习(49):排序数组中查找元素的第一个和最后一个位置

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

题目要求:时间复杂度为:O(logN),而且是有序数组,那一定就是二分法解决了

解法:二分查找

1.左端点

要找一个元素的第一次出现的位置的情况,我们可以把数组分为两个区间,如下:

因为如果mid 落在 <3的区间,可以直接让left = mid + 1,因为答案绝对不可能在 <3 的区间里。

1. mid < target left = mid + 1;

因为如果mid 落在 >=3的区间,就不可以让 right = mid - 1,因为此区间是 >= 3的,所以有可能mid就在此区间第一个 == 3的位置,如果更新right 为 mid - 1,那么就会跑到<3的区间,永远都找不到值。

2.mid >= target right = mid;

3.循环结束条件 while(left < right) 因为上面的逻辑 最后会走到 left == right 才会有最终答案

2.右端点

要找一个元素的最后一次出现的位置的情况,我们可以把数组分为两个区间,如下:

因为如果mid 落在 >3的区间,可以直接让right = mid - 1,因为答案绝对不可能在 >3 的区间里。

1. mid > target right = mid - 1;

因为如果mid 落在 <=3的区间,就不可以让 left = mid + 1,因为此区间是 <= 3的,所以有可能mid就在此区间最后一个 == 3的位置,如果更新left 为 mid + 1,那么就会跑到>3的区间,永远都找不到值。

2.mid <= target left = mid;

3.循环结束条件 while(left < right) 因为上面的逻辑 最后会走到 left == right 才会有最终答案

细节问题

1.数组中没有target的情况

直接先在开始判断 :如果 数组元素为0,返回 {-1,-1}

判断左端点的时候 最后left == right ,只需循环结束后,判断一下 != target 返回{-1,-1}即可.

2.不动问题

求左端点, 如果用右边的 +1 公式求mid,那么最后剩两个元素的时候,如果命中 mid >= target的条件上,那么right不会动,程序陷入死循环, 所以要用不+1的公式。

求右端点, 如果用左边 不+1 公式求mid,那么最后剩两个元素的时候,如果命中 mid <= target的条件上,那么left不会动,程序陷入死循环, 所以要用+1的公式。

cpp 复制代码
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        if(nums.size() == 0)
            return {-1,-1};
        vector<int> ret;
        int mid = 0;
        //1.寻找区间左端点
        int left = 0,right = nums.size()-1;
        while(left<right)
        {
            mid = left + (right - left) /2;
            if(nums[mid] < target) 
                left = mid + 1;
            else if(nums[mid] >= target)
                right = mid;
        }
        //走到这,left = right,找到左端点,但还需判断是不是 == target
        if(nums[left] != target)
            return {-1,-1};
        else
            ret.push_back(left);
        //2.寻找区间右端点
        left = 0,right = nums.size()-1;
        while(left<right)
        {
            mid = left + (right - left + 1) /2;
            if(nums[mid] <= target)
                left = mid;
            else if(nums[mid] > target)
                right = mid - 1;
        }
        //走到这,left = right,找到右端点
        ret.push_back(left);
        return ret;
    }
};
相关推荐
白白白小纯1 小时前
算法篇—返回倒数第k个节点
c语言·数据结构·算法·leetcode
小羊先生car1 小时前
RTOS-F429-HAL-(动/静态)任务的创建(2026/7/27)
开发语言·算法·c#
无忧.芙桃1 小时前
数据结构之堆
c语言·数据结构·c++·算法·
小蒋学算法1 小时前
算法-删除元素后最大固定点数目-典型最长增长序列算法
数据结构·算法
2301_777998341 小时前
Linux线程控制——从线程创建到线程分离(第三部分:线程等待 pthread_join)
linux·运维·服务器·c语言·c++
RD_daoyi1 小时前
Google偷偷给AI引用加了五个新功能:内联引用、悬停预览、品牌展示……但点击率真的回来了吗?
大数据·网络·人工智能·算法·安全·搜索引擎
船漏了就会沉2 小时前
后缀自动机(SAM):字符串处理的“万能瑞士军刀”
算法
醉城夜风~2 小时前
C++模板详解:从基础到高级全面解析
java·开发语言·c++
旺仔学长 哈哈2 小时前
55384 消防安全教育与逃生演练小程序:知识学习、案例浏览和在线演练一站式实现
学习·小程序·消防教育·逃生演练
RuiZN2 小时前
Muduo---Channel类
运维·服务器·c++