手撕大厂笔试之C++STL容器全家桶

目录

个人介绍

前言

map——映射

         本质

定义方法​

时间复杂度

   例题1:

   例题2:

      代码:

      总结: 

vector容器

基本操作

例题1

    代码

    分析

例题2

    代码

pair的用法

基本介绍

用法介绍

例题

    分析

    代码

    总结

优先队列

简介

定义方式

操作方法

应用:迪杰斯特拉最短路

set容器

基本功能

操作方法

操作方法1:查找

例题:

   代码:

操作方法二:找出集合不同的元素的个数

题目1

    分析

    代码

题目2

    分析

    代码 

操作方法三:

例题

    分析

    代码

操作方法四

例题​

    分析

    代码


个人介绍

各位CSDN的友友们,大家好,我是小熙,一个算法小透明,希望在CSDN的大舞台可以和大家一起取得进步(^_^)

个人现状:上个学期在学校的ACM小组学了一个学期的算法,但是世界很大,我的梦想很远,我希望在我年轻的时候可以走出国门,到世界的其他地方看一看,再加上我的算法功底可能真的不太足以支持我在ACM比赛上做出成绩。所以我选择逐渐淡出ACM小组,并把之前的知识整理成博客供大家分享。

学习算法的小方法:知道算法的基本原理——>知道代码实现——>总结出代码模板并熟练于心——>基本模板题——>变式思维题

前言

每当讲到C++STL容器啥的,你是不是总会看到下面的玩意

手撕大厂笔试之C++STL容器全家桶_第1张图片

怎么样,是不是头大了

 手撕大厂笔试之C++STL容器全家桶_第2张图片

但下面,我们就从题目的角度入手,来看看各大容器的哪些用法是刷题有用的,哪些是刷题没用的,至于那些刷题没用的,不会也没关系。引用ACM区域赛金牌大神刁鹏杰学长的话——我们是做题家,不是理论家。

map——映射

本质

表示的是一一映射的关系。

定义方法

map定义方法:

map a;

(1)第一个关键字可以理解为关键字key,每个关键字在map中只出现一次,第二个可以理解为关键字的值value。

(2)key和value可以是任何类型,可以是int,double,string。比如mapa;mapa;

手撕大厂笔试之C++STL容器全家桶_第3张图片

时间复杂度

单次维护和查询的时间复杂度为O(logn)非常优秀

例题1:

map可以用来计数,mapbook通常是桶排序的数组。book[2]就表示的是数组中2出现的次数。

例:给定一个数组a,它的大小长度为n,数组的里面的数据为a1,a2,a3........an。输入一个数据k,判断k在数组中出现的次数。

样例:

5

2 3 5 2 4

输出:

2

#include
using namespace std;
mapbook;
int n;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int temp;
		cin>>temp;
		book[temp]++;
	}
	int k;
	cin>>k;
	cout<

 总结:桶计数是map一个功能之一

例题2:

P5266 【深基17.例6】学籍管理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

手撕大厂笔试之C++STL容器全家桶_第4张图片

代码:

#include
using namespace std;
map book;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x;//x表示的命令
		cin>>x;
		if(x==1)//表示的命令1
		{
		  string t;
		  int y;
		  cin>>t>>y;
		  book[t]=y;	
		  cout<<"OK"<>t;
		   if(!book.count(t)) cout<<"Not found"<>t;
		   if(!book.count(t)) cout<<"Not found"<

总结: 

(1):这个题将map的一一映射的特性体现的淋漓尽致。

(2):以mapbook为例,book.size()表示的是映射容器book中的元素的个数

(3):以mapbook为例,book.count(key)表示查找关键字key的值是否存在

(4):以mapbook为例,book.earse(key)表示清空关键字key的值

vector容器

基本操作

定义:例如vectora,int还可以是double,long long,pair等数据类型

操作:

(1):以vectora为例子,a.push_back(temp)表示向动态数组里面新加入值为temp的元素

(2):以vectora为例子,a.size( )计算动态数组a中的元素的个数

(3):以vectora为例子,!a.empty()查看动态数组a是否为空

例题1

P2671 [NOIP2015 普及组] 求和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

手撕大厂笔试之C++STL容器全家桶_第5张图片

 手撕大厂笔试之C++STL容器全家桶_第6张图片

代码

#include
using namespace std;
typedef long long ll;
const ll mod=10007;
const ll N=1e5+5;
struct node{
	ll num;
	ll color;
}k[N]; 
vectore1[N];
vectore2[N];
int main()
{
	ll n,m;cin>>n>>m;
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
		cin>>k[i].num; 
	}
	for(int i=1;i<=n;i++)
	{
		cin>>k[i].color;
		if(i&1) e1[k[i].color].push_back(i);
		else e2[k[i].color].push_back(i);  
	}
	
	for(int i=1;i<=m;i++)
	{
		int len=e1[i].size();
		ll a,b;
		for(int l=0;l

分析

这道题比较考察数学分析,但也不是特别复杂。不难看出决定三元组变量结果的只有x,y。但是x与y的和是2z,是一个偶数,所以x与y的奇偶性一定要是相同的。然后利用vector进行分类计算就可以了。

例题2

手撕大厂笔试之C++STL容器全家桶_第7张图片

代码

#include
using namespace std;
const int N=1e5+10;
vectore[N];//e[i]表示第i个帖子的ID编号集
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		char temp[6];
		int x,y;
		cin>>temp>>x>>y;
		
		if(temp[0]=='A')
		{
			e[x].push_back(y);
		}
		if(temp[0]=='Q')
		{
			if(y>e[x].size()+1)
			{
				cout<<"-1"<

 总结:有的时候像例一这种数学分类的题和例二这种一对多(一个帖子有多个ID号码)的题目用下vector可能更方便。

pair的用法

基本介绍

个人理解:可以把pair理解为数据类型,地位等同double,int,long long。paira[N]就是pair类型的数组。

引用元素:paira为例,a.first表示引用的是第一个元素,a.second表示引用的是是第二个元素。

关于排序:用STL sort排序pair类型的数组按照的是first元素排列的。

 用法介绍

类似结构体,不过只有两个元素,把这两个元素捆绑在一起。通常在把二维坐标(x,y)或者直线(斜率k和参数b)捆绑在一起当pair。

 例题

手撕大厂笔试之C++STL容器全家桶_第8张图片

 分析

前面在用法介绍那里讲了,看到直线就要想到捆绑"k"和“b”用pair

 代码

#include
using namespace std;
const int N=1e3+10;
int cnt;
struct node{
	int x;
	int y;
}e[N];
typedef pair pdd;
seta;//存储直线
int main()
{
	for(int i=0;i<=19;i++)
	{
		for(int j=0;j<=20;j++)
		{
			e[++cnt].x=i;
			e[cnt].y=j;
		}
	}
    cout<

总结

(1)关于两点的直线的结论

手撕大厂笔试之C++STL容器全家桶_第9张图片

(2)直线相关的问题好要特判平行的情况。

优先队列

简介

与队列的不同是它可以自定义数据的优先级,让优先级高的排在前面,优先出队。

定义方式

priority_queue<数据类型,容器类型,比较方式>

例如:priority_queue,greater> q是大根堆又称升序队列 

           priority_queue,less> q是小根堆又称降序队列 

操作方法

*top:访问的是队头的元素

*size:队列中元素的个数

*push:把元素加到优先队列里面去

*empty:优先队列是否为空

应用:迪杰斯特拉最短路

我水平真的非常有限,只知道优先队列它有这种用法了,抱歉,各位读者。迪杰斯特拉会在图论专题中介绍,先添加一个模板放在这里。

#include
using namespace std;
typedef pair pii;
const int N=2e5+5;
typedef long long ll;
int n,m,s;//s表示的是坐标源点
ll dis[N];
bool vis[N];
vectore[N];

priority_queue,greater> q;
void dijsktra()
{

        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;
        memset(vis,0,sizeof(vis));
        //vis和dis初始化,优先队列
        
        q.push(make_pair(0,s));
        //加入源点loo
        
        while(!q.empty())
        {
                int u=q.top().second;
                q.pop();
                if(vis[u]) continue;
                vis[u]=1;//表示已经入过一次队了
                for(int i=0;idis[u]+w)
                        {
                                dis[v]=dis[u]+w;
                                q.push(make_pair(dis[v],v));
                        }
                }
        }
        //跑迪杰斯特拉
}

int main()
{
        cin>>n>>m>>s;
        for(int i=1;i<=m;i++)
        {
                int x,y,z;
                cin>>x>>y>>z;
                e[x].emplace_back(y,z);
        }
        dijsktra();
        
        for(int i=1;i<=n;i++) cout<

set容器

基本功能

 拥有自动去重和排序的作用。

操作方法

 前言:set的操作方法太多了,一把列举出来的话容易让人云里雾里,就以题目的方式来讲述set的操作方法吧。

 操作方法一:查找

(1)以seta为例子,a.count(k)表示set集合里面是否存在k这个数据。

(2)以seta为例子,a.find(k)==a.end()表示set集合里面不存在k这个数据。反之表示存在k这个数据。

总结:以上两种操作方法的作用是查找。

例题:

给出一个长度大小为n的数组a,数组中的元素个数为a1,a2,a3.......an-1,an,请输入一个数字k,判断数组中是否有k这个数,有的话输入"OK"无的话输入“NO”

样例:

5

2 3 2 4 6 

4

输出

OK 

代码:

#include
using namespace std;
const int N=1e3+10;
seta;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;
		a.insert(t);
	}
	int k;
	cin>>k;
	if(a.count(k)) cout<<"OK";
	else
	cout<<"NO"<
#include
using namespace std;
const int N=1e3+10;
seta;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;
		a.insert(t);
	}
	int k;
	cin>>k;
	if(a.find(k)!=a.end()) cout<<"OK";
	else
	cout<<"NO"<

操作方法二:找出集合不同的元素的个数

以seta为例子,a.size()表示的是集合a中不同元素的个数

题目1

P3370 【模板】字符串哈希 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

手撕大厂笔试之C++STL容器全家桶_第10张图片

分析

看到不同二字,立马想到set,然后没了。

代码

#include
using namespace std;
int main()
{
	int n;cin>>n;
	string p;
	seta;
	for(int i=1;i<=n;i++)
	{
		cin>>p;
		a.insert(p);
	}
	cout<

 题目2

手撕大厂笔试之C++STL容器全家桶_第11张图片

分析

转化为斜率k来分析,求斜率k不同的数量 

代码 

#include
using namespace std;
seta;
int cnt;
int main()
{
	int n;cin>>n;
	double x0,y0;
	cin>>x0>>y0;
	for(int i=1;i<=n;i++)
	{
		double x1,y1;
		cin>>x1>>y1;
		if(x1==x0) 
		{
		   cnt=1;
		   continue;	
		}
		double temp=(y1-y0)/(x1-x0);
		a.insert(temp);
	}
	cout<

 操作方法三:

(1):auto定义stl的迭代器,在遍历stl的时候需要用迭代器来遍历。这里的迭代器可以把他理解为指针。

(2):a.lower_bound(x)返回的是迭代器,在写的时候经常写成auto it=lower_bound(x)

(3):以seta为例,a.erase(x)表示的是删除操作,删除set集合中的x值

 例题

P5250 【深基17.例5】木材仓库 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

手撕大厂笔试之C++STL容器全家桶_第12张图片

分析

看到“保障没有两个木材长度相同”,直接set

代码

#include
using namespace std;
seta;
int n;
int main()
{
	int n;cin>>n;
	while(n--)
	{
		int x,y;
		cin>>x>>y;//x表示的是命令,1的话就是进货,2的话就是出货
		
		if(x==1)
		{
			if(!a.count(y))
			{
				a.insert(y);
			}
			else
			{
				cout<<"Already Exist"<

操作方法四

迭代器iterator,遍历容器的作用。

通常写法:for(set::iterator it=a.begin():it!=a.end();it++)

例题

手撕大厂笔试之C++STL容器全家桶_第13张图片

 分析

本题虽然与集合相关,但是把set中的元素提取到数组里面的过程用了上面讲的迭代器的遍历

代码

#include
using namespace std;
typedef pair pdd;
seta;//先用set容器装直线,对直线进行去重操作
const int N=1e3+10;
pdd b[N];//以数组的方式存储去重之后的直线
int n;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		double x,y;
		cin>>x>>y;
		a.insert({x,y});
	}
	int cnt=0;
	
	for(set::iterator it=a.begin();it!=a.end();it++,++cnt)//这是以迭代器的方式遍历set容器里面的每一个元素,背下来就可以了,反正搞明白也意义不大
	{
		double x=it->first;double y=it->second;
		pdd temp;
		temp.first=x;
		temp.second=y;
		b[cnt]=temp;
	}//这一个部分的作用遍历set里面的每一个元素然后把他提取到数组b里面去
	
	int ans=2;
	
	//这一个步骤就是枚举直线了,第一层循环枚举2~i的每一个直线,第二层循环是第i条直线之前二代每一条直线。
	
	for(int i=2;i<=cnt;i++)
	{
		sett;//sett用来装第i条加入的直线与之前加入的直线的交点
		for(int j=1;j

你可能感兴趣的:(蓝桥杯,c++,算法)