【C++】 详解 lower_bound 和 upper_bound 函数(看不懂来捶我!!!)

目录

一、前言

二、函数详解 

🥝 lower_bound

🍍upper_bound

 三、常考面试题

 四、共勉


一、前言

这两个函数是我在 LeetCode 上做题见到,看到不熟悉的函数 lower_bound 和 upper_bound让我感觉很难受,于是在 C++ 官网去学习,例子就一个是最基础的,我看明白了。虽然是两个函数的接口就两个,但是有时候看别人使用的时候,里面参数还可以放不同的仿函数,我懵逼了。就去网上搜,但是大家讲解的都是它的第一个接口。我只能再把文档一遍一遍过,代码一遍遍的尝试,调试。最终通过查阅资料将其总结如下。

二、函数详解 

        首先,大家都说用这两个函数之前必须是在有序的数组中,但是都没有说明为什么是在有序的数组,因为他们的底层实现是二分查找(这个也是我在别人的题解的时候知道的)。如果对二分查找有不清楚的伙伴可以看看这篇文章:详解二分查找

 🥝 lower_bound

 函数原型:

原型1

template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,  const T& val);

 原型2

template <class ForwardIterator, class T, class Compare>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

模板参数解释:

  1. ForwardIterator就是一个迭代器,vector< int > v,v数组的首元素就是 v.begin()
  2. T&val , 就是一个T类型的变量
  3. Compare 就是一个比较器,可以传仿函数对象,也可以传函数指针

 函数作用:

  • 前提是有序的情况下lower_bound 返回指向第一个值不小于 val 的位置,也就是返回第一个大于等于val值的位置。(通过二分查找) 

参数、返回值含义 :

  1. first,last: 迭代器在排序序列的起始位置和终止位置,使用的范围是[first,last).包括first到last位置中的所有元素
  2. val: 在[first,last)下,也就是区分(找到大于等于val值的位置,返回其迭代器)
  3. comp 主要针对于原型二,传一个函数对象,或者函数指针,按照它的方式来比较
  4. 返回值返回一个迭代器,指向第一个大于等于val的位置

 举例说明:

 原型一 例1

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
	vector<int> v = { 3,4,1,2,8 };
	// 先排序
	sort(v.begin(), v.end());  // 1 2 3 4 8

	// 定义两个迭代器变量
	vector<int>::iterator iter1;
	vector<int>::iterator iter2;

	// 在动态数组中寻找 >=3 出现的第一个数 并以迭代器的形式返回
	iter1 = lower_bound(v.begin(), v.end(), 3);  // -- 指向3
	// 在动态数组中寻找 >=7 出现的第一个数 并以迭代器的形式返回
	iter2 = lower_bound(v.begin(), v.end(), 7);  // -- 指向8

	cout << distance(v.begin(), iter1) << endl; //下标 2
	cout << distance(v.begin(), iter2) << endl; //下标 4 
	return 0;
}

 注意:需要注意的是如果例子中(val >= 8),那么迭代器就会指向last位置,也就是数组尾元素的下一个,不管val多大,迭代器永远指向尾元素的下一个位置

 原型二例2

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;


int main()
{
	vector<int> v = { 3, 4, 1, 2, 8 };
	// 无序数组,不用sort排序,下面调用lower_bound排序

	// 定义两个迭代器变量 
	vector<int>::iterator iter1;
	vector<int>::iterator iter2;

	//less<int>() 是建小堆,排升序。
    //greater<int>() 是建大堆,排降序
	//所以数组 v = {1,2,3,4,8} 
	//我们找第一个比1大的,那肯定就是首元素1了
	//我们找第一个比8大的,没有,所以就指向数组最后一个元素8了
	iter1 = lower_bound(v.begin(), v.end(), 1, less<int>());//
	iter2 = lower_bound(v.begin(), v.end(), 8, less<int>());//

	cout << iter1 - v.begin() << endl; //下标 所以就是 0
	cout << iter2 - v.begin() << endl; //下标 所以就是 4
	system("pause");
}

  注意:我们原型2的第四个参数(比较器)可以用来排序,再来获取大于等于val值的迭代器

  •  less<int>() 是建小堆,排升序。
  • greater<int>() 是建大堆,排降序

 原型三 例3 仿函数传参

typedef struct Student
{
	int _id;  //学号
	int _num; //排名

	Student(int id, int num)
		:_id(id)
		, _num(num)
	{}
	
}Stu;

struct CompareV
{
	bool operator() (const Stu& s1,  const Stu& s2)//  排名升序
	{	
		return s1._num < s2._num;
	}
};

int main()
{
	vector<Stu> vS = { { 101, 34 }, { 103, 39 }, { 102, 35 } };


	//CompareV()排完序后是这个丫子
	//101 34
	//102 35
    //103 39
	auto iter = lower_bound(vS.begin(), vS.end(), Stu(200,33), CompareV());
	cout << iter - vS.begin() << endl; //我们就找到了按仿函数排序(找排名比33大的位置 就是0)
	system("pause");
}

 我们了解了lower_bound的用法以后,我们再来了解一下lower_bound的原型实现 ----二分查找实现

lower_bound的底层实现 

int lower_bound(vector<int>& nums, int x) 
{
	int left = 0;
	int right = nums.size() - 1;
    // 区间为 左闭右闭
	while (left <= right) {
		int mid = left +(right - left) / 2;
		if (x > nums[mid]) {
			left = mid + 1;
		}
		else {
			right = mid - 1;	
		}
	}
	return left;
}

🍍upper_bound

      用法和上面类似。只是把lower_bound的 【大于等于】 换成 【大于】 。仿函数等等全是相同的用法

底层实现 

int upper_bound(vector<int>& nums, int x) {
	int left = 0;
	int right = nums.size() - 1;

	while (left <= right) {
		int mid = left +(right - left) / 2;
		if (x >= nums[mid]) {       //这里是大于等于
			left = mid + 1;
		}
		else {
			right = mid - 1;	
		}
	}
	return left;
}

 三、常考面试题

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

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
         if(nums.size()==0)
         {
            return {-1,-1};
         }

         // 返回第一个 大于等于 target 的迭代器
         auto index1 = lower_bound(nums.begin(),nums.end(),target);
         // 返回第一个 大于 target 的迭代器
         auto index2 = upper_bound(nums.begin(),nums.end(),target);

         // 这个值不存在 或者 这个数不存在
         if(index1==nums.end() || *index1!=target)
         {
            return {-1,-1};
         }

         // 存在
         return {(int)distance(nums.begin(),index1),(int)distance(nums.begin(),index2-1)};
    }
};

 四、共勉

以下就是我对 lower_bound 和 upper_bound 函数 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对 C++ 的更新,请持续关注我哦!!!  

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java入门基础知识第七课(超基础,超详细)——数组

前面二白讲了选择结构和循环结构&#xff0c;动手的同学会发现已经有了一定的难度&#xff0c;后面二白会专门收集一些经典的题目&#xff0c;训练多了才能让记忆更加深刻&#xff0c;这次咱们讲一下数组。 一、数组的定义 什么是数组呢&#xff0c;我们都知道变量是存储数据的…

数字乡村发展:推动农村现代化进程

随着信息技术的迅猛发展和数字化浪潮的深入推进&#xff0c;数字乡村发展已成为推动农村现代化进程的重要力量。数字乡村不仅是乡村振兴战略的重要组成部分&#xff0c;也是实现农村经济社会全面发展的重要途径。本文将从数字乡村的内涵、发展现状、面临的挑战以及发展策略等方…

聚类算法的先验基础知识

聚类算法的先验基础知识 1. 瑞利商2. 谱定理3. 联合概率4. 条件概率分布5. 边缘分布6. 贝叶斯定理7. 有向图8. 拉格朗日乘子定理 下一篇将介绍整理各种聚类算法&#xff0c;包括k-means&#xff0c;GMM(Guassian Mixture Models, 高斯混合)&#xff0c;EM(Expectation Maximiza…

Docker速成:新手变专家!

Docker介绍 容器历史 1、Chroot Jail 就是常见的chroot命令的用法。它在1979年的时候就出现了&#xff0c;被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。 2、The FreeBSD Jail &#xff08;监狱&#xff09;实现了操作系统级别的虚拟化&#xff0c;他…

java中使用雪花算法(Snowflake)为分布式系统生成全局唯一ID

&#xff08;全局唯一ID的解决方案有很多种&#xff0c;这里主要是介绍和学习Snowflake算法&#xff09; 什么是雪花算法&#xff08;Snowflake&#xff09; 雪花算法&#xff08;Snowflake Algorithm&#xff09;是由Twitter公司在2010年左右提出的一种分布式ID生成算法&…

一起学习python——基础篇(10)

前言&#xff0c;Python 是一种面向对象的编程语言。以前大学读书的时候经常开玩笑说的一句话“如果没有对象&#xff0c;就new一个”。起因就是编程老师上课时经常说一句“首先&#xff0c;我们new一个对象”。 今天讲一下python的类和对象。 类是什么&#xff1f;它是一种用…

应用商店备案登记流程解析

引言&#xff1a; 随着智能手机的普及和移动互联网的发展&#xff0c;移动应用程序&#xff08;App&#xff09;已成为人们日常生活中不可或缺的一部分。在开发一个App之后&#xff0c;开发者需要将其上传到应用商店进行审核和上架。然而&#xff0c;在上架之前&#xff0c;开…

项目管理-Jiar Software

文章目录 前言Jira 中的关键词或术语功能应用场景优势 总结 前言 Jira Software 是由澳大利亚公司 Atlassian 开发的一款领先的敏捷项目管理工具&#xff0c;广泛应用于软件开发团队&#xff0c;以支持复杂的项目管理需求。以下是关于 Jira Software 的详细介绍&#xff0c;包…

银行内部控制管理系统应用架构最全介绍

内部控制管理系统 实物资产管理系统 依据《企业内部控制应用指引第 8 号——资产管理》&#xff0c;金融企业应当建立实物资产管理的岗位责任制度&#xff0c;对实物资产的验收入库、领用、发出、盘点、保管及处置等关键环节进行控制&#xff0c;防止各种实物资产被盗、毁损和…

mac中创建的证书提示是无效或者是证书不受信任的解决办法

mac中创建的证书提示是无效或者是证书不受信任的解决办法 原因&#xff1a; &#xff08;1&#xff09;可能是由于自己的误删除将Apple worldwide Developer Relatioans Certification Authority删除掉了 (2) 由于签发的认证的证书到期了 &#xff08;3&#xff09;其它未知原…

【趣味学算法】14_梅森素数

注&#xff1a; 本系列仅为个人学习笔记&#xff0c;学习内容为《算法小讲堂》&#xff08;视频传送门&#xff09;&#xff0c;通俗易懂适合编程入门小白&#xff0c;需要具备python语言基础&#xff0c;本人小白&#xff0c;如内容有误感谢您的批评指正 梅森数&#xff08;Me…

ML Kit:通过Mendix 集成人脸识别算法

预训练模型是一种已经使用训练数据集进行训练并包含执行模型所需所有参数的机器学习模型。这类模型常用于计算机视觉领域&#xff0c;比如可以在Mendix Studio Pro中导入ONNX模型后&#xff0c;可以在微流程中执行该模型。 本文讲述如何在Mendix应用程序中集成特定的人脸检测模…

短视频培训要多少钱?

在互联网时代&#xff0c;短视频已经成为一种流行的传播方式&#xff0c;不仅可以记录生活的美好瞬间&#xff0c;还可以作为一种职业技能&#xff0c;帮助个人或企业实现品牌推广和商业变现。因此&#xff0c;越来越多的人开始关注短视频制作培训&#xff0c;希望通过专业的学…

SQL语言自用(持续更新)(带例子)

目录 基础知识数据定义数据查询单表查询连接查询嵌套查询集合运算 实验例子数据定义数据查询单表查询查询的目标表达式为所有列、指定的列或指定的列的运算三种不同。使用DISTINCT保留字消除重复行。对查询结果排序和分组。集合分组使用集函数进行各项统计。 连接查询笛卡儿连接…

【QT入门】 Qt自定义控件与样式设计之QComboBox样式表介绍

往期回顾 【QT入门】 Qt自定义控件与样式设计之QLineEdit的qss使用-CSDN博客 【QT入门】Qt自定义控件与样式设计之QPushButton常用qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬浮按钮弹出对话框-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QComb…

LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量

LabVIEW和2D激光扫描的受电弓滑板磨耗精确测量 在电气化铁路运输中&#xff0c;受电弓滑板的健康状况对于保障列车安全行驶至关重要。受电弓滑板作为连接电网与列车的直接介质&#xff0c;其磨损情况直接影响到电能的有效传输及列车的稳定运行。精确、快速测量受电弓滑板磨损情…

天池医疗AI大赛[第一季] Rank5解决方案

一、赛题说明 数据格式 本次大赛数据集包含数千份高危患者的低剂量肺部CT影像&#xff08;mhd格式&#xff09;数据&#xff0c;每个影像包含一系列胸腔的多个轴向切片。每个影像包含的切片数量会随着扫描机器、扫描层厚和患者的不同而有差异。原始图像为三维图像。这个三维图…

力扣经典150题(1)

文章目录 6.Z字形变换82.删除排序链表中的重复元素||61.旋转链表100.相同的树 6.Z字形变换 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1…

【讲解如何OpenCV入门】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

数据库之DQL操作(数据查询语言)

DQL英文全称是Data Query Language(数据查询语言)&#xff0c;数据查询语言&#xff0c;用来查询数据库中表的记录。查询关键字: SELECT。 本节介绍以下表为例&#xff1a; create table emp(id int comment 编号&#xff0c;workno varchar(10) comment 工号&#xff0c;nam…