LeetCode34.在排序数组中查找元素的第一个和最后一个位置

题目

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

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

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例

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

思路

二分查找思路解释:

  1. 首先判断数组是否为空,如果为空,则直接返回 {-1, -1},表示找不到目标值在数组中的范围。
  2. 初始化一个长度为 2 的结果数组 result,初始值为 {-1, -1},用于存储最终的结果。
  3. 使用二分查找的思想,在数组 nums 中寻找目标值的起始位置:
    • 初始化搜索范围为 [0, n-1],其中 n 为数组长度。
    • 不断缩小搜索范围,直到左指针 l 和右指针 r 相遇。
    • 在每一步中,计算中间位置 mid,并根据 nums[mid] 与目标值 target 的关系调整左右指针的位置。
    • 最终得到的 l 即为目标值的起始位置,如果 nums[l] 不等于目标值,则说明数组中不存在目标值,直接返回 {-1, -1}。
  4. 如果找到了目标值的起始位置,将其存储在 result[0] 中。
  5. 然后重新初始化左右指针,进行二分查找目标值的结束位置:
    • 同样采用二分查找的思想,在数组中寻找目标值的结束位置。
    • 不断缩小搜索范围,直到左指针 l 和右指针 r 相遇。
    • 在每一步中,计算中间位置 mid,并根据 nums[mid] 与目标值 target 的关系调整左右指针的位置。
    • 最终得到的 l 即为目标值的结束位置。
  6. 将结束位置存储在 result[1] 中,最终返回 result。

这样,代码通过两次二分查找,可以找到目标值在数组中的起始位置和结束位置,并且满足了 O(log n) 的时间复杂度要求。

Code

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.empty()){return {-1, -1};}vector<int> result(2, -1);int n = nums.size();int l = 0,r= n-1;while(l<r){int mid = (l+r)>>1;if(nums[mid]>=target)r=mid;else l = mid+1;}if(nums[l]!=target)return {-1,-1};else {result[0]=l;l=0,r=n-1;while(l<r){int mid = (l+r+1)>>1;if(nums[mid]<=target)l=mid;else r=mid-1;}result[1]=l;return result;}}
};

下面是代码的执行效率
在这里插入图片描述
当然我们也可以用更简便的二分查找lower_bound() upper_bound()函数求解:

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {auto first = lower_bound(nums.begin(), nums.end(), target);auto last = upper_bound(nums.begin(), nums.end(), target);if (first == nums.end() || *first != target) {return {-1, -1};} else {return {static_cast<int>(first - nums.begin()), static_cast<int>(last - nums.begin() - 1)};}}
};

这段代码实现了在一个按非递减顺序排列的整数数组中查找目标值的起始位置和结束位置,使用了 C++ 标准库中的 lower_bound() 和 upper_bound() 函数。下面是代码的解释:

  1. 首先,使用 lower_bound(nums.begin(), nums.end(), target) 函数在排序后的数组 nums 中找到第一个不小于目标值 target 的元素的迭代器,赋值给变量 first。

  2. 然后,使用 upper_bound(nums.begin(), nums.end(), target) 函数在排序后的数组 nums 中找到第一个大于目标值 target 的元素的迭代器,赋值给变量 last。

  3. 接着,通过比较 first 是否等于 nums.end() 或 *first 是否等于 target,来判断是否找到了目标值:

    • 如果 first == nums.end(),表示没有找到目标值,直接返回 {-1, -1}。
    • 如果 *first != target,表示没有找到目标值,直接返回 {-1, -1}。
    • 否则,继续执行下面的逻辑。
  4. 最后,根据找到的位置返回结果:

    • 返回 {static_cast(first - nums.begin()), static_cast(last - nums.begin() - 1)},即将第一个出现位置和最后一个出现位置的下一个位置转换为整数,并放入结果数组中返回。

通过使用 lower_bound() 和 upper_bound() 函数,可以非常简洁地实现在排序数组中查找目标值的起始位置和结束位置,避免了手动编写二分查找的复杂逻辑。

但是执行效率不如手写二分查找高
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/501291.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享fastapi低级错误

我是创建表的时候把__tablename__ 写成__table__然后一直报这个错误

每日一类:Qt GUI开发的基石《QWidget》

深入探索QWidget&#xff1a;Qt GUI开发的基石 在Qt框架中&#xff0c;QWidget类扮演着构建图形用户界面&#xff08;GUI&#xff09;的基础角色。它不仅提供了窗口的基本功能&#xff0c;还允许开发者通过继承和定制来创建各式各样的用户界面元素。本文将详细介绍QWidget的关…

抢单情况下的均衡分配机制

背景&#xff1a; 1、工单有多种类型。 2、客户提交工单。 3、不同客服受理不同类型工单&#xff0c;受理工单类型存在交叉。 4、按照类型维度实现均衡分配。 方案&#xff1a; 1、为每种类型创建一个工单池&#xff0c;使用队列&#xff0c;左进右出&#xff1b;客户提交…

Excel中使用ROW函数自动更新行号或编号

操作步骤&#xff1a; 1、在编号“1”的单元格输入公式“ROW()-1”&#xff1b; 2、在上一步填好公式的单元格基础上下拉填充&#xff0c;即可批量得到编号&#xff0c;如果删掉其中的一行或几行&#xff0c;编号会自动进行更新。

JavaScript-关于事件、事件流(捕获、冒泡)、事件源、常用事件

1.如何注册事件(如何绑定事件) ​ 何为注册事件&#xff0c;就是给元素添加事件&#xff0c;其方式有传统注册事件、方法监听注册事件。 0、1级事件&#xff08;传统注册事件&#xff09;不允许多个响应程序 我们在元素内或js内使用on的方式就是传统注册事件&#xff0c;这种形…

机器学习YOLO操作全流程​​编

YOLO介绍 Ultralytics YOLOv8,是最新的著名实时目标检测和图像分割模型。它基于深度学习和计算机视觉的最新进展,提供了无与伦比的速度和精度性能。由于其精简的设计,适用于各种应用,并且可以轻松适配不同的硬件平台,从边缘设备到云端API。 探索 YOLOv8 文档,这是一个全…

k8s部署 多master节点负载均衡以及集群高可用

一、k8s 添加多master节点实验 1、master02节点初始化操作 2、在master01节点基础上&#xff0c;完成master02节点部署 ①从master01节点复制所需要的文件 需要从master01节点复制etcd数据库所需要的ssl证书、kubernetes安装目录&#xff08;二进制文件、组件与apiserver通信…

基于springboot+vue的党员教育和管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

day05_用户管理minIO角色分配(页面制作,查询用户,添加用户,修改用户,删除用户,用户头像,查询所有角色,保存角色数据)

文章目录 1 用户管理1.1 页面制作1.2 查询用户1.2.1 需求说明1.2.2 后端接口需求分析SysUserSysUserDtoSysUserControllerSysUserServiceSysUserMapperSysUserMapper.xml 1.2.3 前端对接实现思路sysUser.jssysRole.vue 1.3 添加用户1.3.1 需求说明1.3.2 页面制作1.3.3 后端接口…

基于docker实现MySQL主从复制(全网最详细!!!)

一、 通过docker镜像搭建MySQL主从 主服务器&#xff1a;容器名zi-mysql-master&#xff0c;端口3306 从服务器&#xff1a;容器名zi-mysql-slave1&#xff0c;端口3307 从服务器&#xff1a;容器名zi-mysql-slave2&#xff0c;端口3308 二、 关闭防火墙&#xff0c;启动docker…

Executable and Linkable Format(ELF)

File layout ELF文件有两种视图。程序头表&#xff08;Program Header&#xff09;显示在运行时使用的段&#xff08;Segments&#xff09;&#xff0c;而节头表&#xff08;Section Header&#xff09;则列出了二进制文件的所有节&#xff08;Sections&#xff09;的集合。程…

buuctf_misc_面具下的flag

题目tm: 看到《你的名字》的联动&#xff0c;我开始做这题是很开心的。但&#xff01;这题我要狠狠的记录&#xff01;下面开始我的解题历程&#xff1a; winhex&#xff0c;没看到啥&#xff0c;但看出来图片里面藏东西了 LSB看一眼&#xff0c;没啥。图片属性&#xff0c;没…