【面试经典 150 | 二分查找】在排序数组中查找元素的第一个和最后一个位置

文章目录

  • 写在前面
  • Tag
  • 题目来源
  • 题目解读
    • 方法一:二分查找
    • 方法二:使用库函数
  • 知识回顾
    • 二分查找的三种写法与三个问题
    • 常用的二分库函数
  • 写在最后

写在前面

本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……

专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:

  • Tag:介绍本题牵涉到的知识点、数据结构;
  • 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
  • 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
  • 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
  • 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。

Tag

【数组】【二分查找】


题目来源

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


题目解读

方法一:二分查找

对于有序数组中搜索指定元素问题,我们应该优先想到二分查找方法。题目有要求解法的时间复杂度必须为 O ( l o g n ) O(logn) O(logn),那本题基本确定需要使用二分查找法解题。

思路

我们只需要写出一个函数找出数组中 target 第一次出现的位置。使用二分查找轻松实现。还有一些实现细节,见代码中的注释。

代码

class Solution {
public:// 【闭区间写法】找出 nums[i] >= target 的最小的 iint lower_bound(const vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left <= right) {     // 区间不为空// 注意指针的指向变化int mid = left + ((right - left) >> 1);if (nums[mid] < target) {left = mid + 1;}else {right = mid - 1;}}return left;}vector<int> searchRange(vector<int>& nums, int target) {int start = lower_bound(nums, target);if (start == nums.size() || nums[start] != target) {return {-1, -1};}// 如果 start 存在,那么 end 必定存在int end = lower_bound(nums, target + 1) - 1;return {start, end};}
};

复杂度分析

时间复杂度: O ( l o g n ) O(logn) O(logn)

空间复杂度: O ( 1 ) O(1) O(1)

方法二:使用库函数

对于上述手写二分查找的函数,C++ 标准库中有对应的函数 lower_bound \texttt{lower\_bound} lower_bound 实现相同的功能。不论是库函数,还是手写二分查找都需要掌握。

代码

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int start = lower_bound(nums.begin(), nums.end(), target) - nums.begin();if (start == nums.size() ||  nums[start] != target) {return {-1, -1};}int end = lower_bound(nums.begin(), nums.end(), target + 1) - nums.begin() - 1;return {start, end};}
};

知识回顾

二分查找的三种写法与三个问题

二分查找有三种写法:闭区间、左闭右开和开区间写法,无论是哪种写法,始终都要关注三个问题:

  • 何时退出循环,二分查找据此有了三种写法
  • 指针如何移动
  • 最后返回什么

关于以上三种写法与三个问题,可以参考 【面试经典 150 | 二分查找】搜索插入位置。

常用的二分库函数

lower_bound(beg, end, val) \texttt{lower\_bound(beg, end, val)} lower_bound(beg, end, val)
返回一个迭代器,表示 第一个不小于(大于等于) val 的元素,如果不存在这样的元素则返回 end 迭代器。
upper_bound(beg, end, val) \texttt{upper\_bound(beg, end, val)} upper_bound(beg, end, val)
返回一个迭代器,表示 第一个大于 val 的元素,如果不存在这样的元素则返回 end 迭代器。
equal_range(beg, end, val) \texttt{equal\_range(beg, end, val)} equal_range(beg, end, val)
返回一个 pair,其 first 成员是 lower_bound \texttt{lower\_bound} lower_bound 返回的迭代器,second 成员是 upper_bound \texttt{upper\_bound} upper_bound 返回的迭代器。
binary_search(beg, end, val) \texttt{binary\_search(beg, end, val)} binary_search(beg, end, val) 返回一个 bool 值,指出序列中是否包含等于 val 的值。

以上每一个函数都提供一个第二版本,这个版本可以自定义比较操作。

写在最后

如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。

最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。

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

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

相关文章

二叉树的层次遍历(配图详解)

二叉树的层次遍历 层序遍历顾名思义就是一层一层的遍历的树中的所有结点。 typedef char EmpeType 在本篇文章中&#xff0c;将char类型使用EmpeType&#xff1b; typedef char EmpeType;创建一个结构体 typedef struct BiTNode {EmpeType data; //数据域struct BiTNode* …

使用docker配置CCM-SLAM

一.Docker环境配置 1.拉取Docker镜像 sudo docker pull ubuntu:18.04拉取的为ununtu18版本镜像&#xff0c;环境十分干净&#xff0c;可以通过以下命令查看容器列表 sudo docker images 如果想删除多余的docker image&#xff0c;可以使用指令 sudo docker rmi -f <id&g…

“开关是灯的日出日落,日出日落是灯的开关”

C语言刷题 day01 本篇是C语言刷题大杂烩&#xff0c;收集了笔者遇到的认为有价值的题目&#xff0c;本篇会持续更新~~ day01 至少是其他数字两倍的最大数 题目原文&#xff1a; 题意解析&#xff1a; 请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 …

符文协议的演变历程:从挑战到创新

在比特币网络长期面临的挑战中&#xff0c;与主流去中心化金融功能的兼容性一直是一大难题。相比之下&#xff0c;以太坊通过ERC-721和ERC-1155代币标准&#xff0c;为NFT和去中心化金融应用提供了支持&#xff0c;而比特币的应用范围却相对有限。然而&#xff0c;近年来&#…

蓝桥杯2024年第十五届省赛真题-爬山

贪心优先队列的题&#xff0c;贪心会漏一个情况&#xff0c;不知道怎么处理&#xff0c;这里直接打表了 2 1 1 48 49 答案是30&#xff0c;贪心是31 专有名词&#xff1a;hack-有新的测试点过不了 #include<bits/stdc.h> using namespace std; #define endl \n #define …

取模学习之Image2Lcd

使用软件Image2Lcd V0.4 1.&#xff1a;打开图片&#xff0c;图片格式可选如下图&#xff0c;本文使用的.jpg格式 转换后数组例子&#xff08;数组头数据占前8字节&#xff09;&#xff1a; 2.&#xff1a;扫描模式 由第1个字节低四位配置 &#xff08;1&#xff09;水平扫描 …

动手学深度学习11 权重衰退

动手学深度学习11 权重衰退 1. 权重衰退2. 代码实现3. QA 视频&#xff1a; https://www.bilibili.com/video/BV1UK4y1o7dy/?spm_id_fromautoNext&vd_sourceeb04c9a33e87ceba9c9a2e5f09752ef8 电子书&#xff1a; ttps://zh-v2.d2l.ai/chapter_multilayer-perceptrons/wei…

【MySQL 数据宝典】【内存结构】- 004 自适应哈希索引

自适应哈希索引 https://developer.aliyun.com/article/1230086 什么是自适应哈希索引&#xff1f; 自适应哈希索引是MySQL InnoDB存储引擎中的一种索引结构&#xff0c;用于加速查询。它根据查询模式和数据分布动态地调整自身的大小&#xff0c;以提高性能。 上图就是通过…

Redis中的订阅发布和事务(一)

订阅发布 PUBSUB NUMSUB PUBSUB NUMSUB [channel-1 channel-2… channel-n]子命令接受任意多个频道作为输入参数&#xff0c;并返回这些频道的订阅者数量。 这个子命令是通过pubsub_channels字典中找到频道对应的订阅者链表&#xff0c;然后返回订阅者链表的长度来实现的(订阅…

Nuclei 减少漏报的使用小技巧

在最近工作的渗透测试项目中发现Nuclei存在一个问题&#xff0c;就是相同的网站连续扫描多次会出现漏报的情况&#xff0c;此前没有注意过这个情况&#xff0c;所以写篇文章记录一下。 在此之前我的常用命令都是一把梭&#xff0c;有就有没有就继续其他测试 $ nuclei -u htt…

患者关系管理系统功能详解

脉购健康管理系统&#xff08;软件&#xff09;包含&#xff1a;客户开卡、健康档案、问卷调查、问诊表、自动设置标签、自动随访、健康干预、健康调养、历年指标趋势分析、疾病风险评估、饮食/运动/心理健康建议、同步检查报告数据、随访记录、随访电话录音、健康阶段总结、打…

Java - 阿里巴巴命名规范

文章目录 前言一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 日期时间(六) 集合处理(七) 并发处理(八) 控制语句(九) 注释规约(十) 前后端规约(十一) 其他 二、异常日志(一) 错误码(二) 异常处理(三) 日志规约 三、单元测试四、安全规约五、MySQL 数据…

2024面试软件测试,常见的面试题(上)

一、综合素质 1、自我介绍 面试官您好&#xff0c;我叫XXX&#xff0c;一直从事车载软件测试&#xff0c;负责最多的是中控方面。 以下是我的一些优势&#xff1a; 车载的测试流程我是熟练掌握的&#xff0c;且能够独立编写测试用例。 平时BUG提交会使用到Jira&#xff0c;类似…

电缆检测仪的正确使用方法有哪些步骤?

电缆检测仪的正确使用方法是&#xff1a;首先&#xff0c;确保检测仪电源充足&#xff0c;设备完好无损&#xff1b;其次&#xff0c;根据电缆类型和故障类型选择合适的测试模式和参数&#xff1b;接着&#xff0c;将检测仪与电缆正确连接&#xff0c;确保接触良好&#xff1b;…

深入挖掘C语言 ----动态内存分配

开篇备忘录: "自给自足的光, 永远都不会暗" 目录 1. malloc和free1.1 malloc1.2 free 2. calloc和realloc2.1 calloc2.2 realloc 3. 总结C/C中程序内存区域划分 正文开始 1. malloc和free 1.1 malloc C语言提供了一个动态开辟内存的函数; void* malloc (size_t s…

python处理IP对应城市省份

python处理IP对应城市省份 IP地理地址库geoip2用法 数据包下载 数据包下载地址&#xff08;需要注册&#xff09; https://www.maxmind.com/en/accounts/258630/geoip/downloads 考虑到注册麻烦&#xff0c;可以到下面这个github的链接去直接下载 https://github.com/Hackl0…

2024-9.python文件操作

文件操作 引言 到目前为止&#xff0c;我们做的一切操作&#xff0c;都是在内存里进行的&#xff0c;这样会有什么问题吗&#xff1f;如果一旦断电或发生意外关机了&#xff0c;那么你辛勤的工作成果将瞬间消失。是不是感觉事还挺大的呢&#xff1f;现在你是否感觉你的编程技…

【Java EE】依赖注入DI详解

文章目录 &#x1f334;什么是依赖注入&#x1f340;依赖注入的三种方法&#x1f338;属性注入(Field Injection)&#x1f338;构造方法注入&#x1f338;Setter注入&#x1f338;三种注入优缺点分析 &#x1f333;Autowired存在的问题&#x1f332;解决Autowired对应多个对象问…

动态库静态库linux

动态库静态库 静态库 静态库必须包含在可执行文件里&#xff0c;整个都要包含 缺点&#xff1a;消耗系统大&#xff0c;每个使用静态库的程序都要复制静态库&#xff08;浪费内存&#xff09; 影响使用场景&#xff1a; 在静态库内存小的时候&#xff0c;可以用来提升速度 制…

Scala 03 —— Scala Puzzle 拓展

Scala 03 —— Scala Puzzle 拓展 文章目录 Scala 03 —— Scala Puzzle 拓展一、占位符二、模式匹配的变量和常量模式三、继承 成员声明的位置结果初始化顺序分析BMember 类BConstructor 类 四、缺省初始值与重载五、Scala的集合操作和集合类型保持一致性第一部分代码解释第二…