STL容器的高级玩法
写在前面:本人于2020PAT甲级取得满分(见本人其他博客),在刷题过程中我有了很多自己的小经验和技巧,在这里分享给大家,祝大家刷题顺利,早日拿到免费的PAT徽章~~
注意:这里是分享小技巧,并不是全面介绍容器,此处默认你已经掌握了容器的基本用法!
1. Vector
大名鼎鼎的Vector,动态数组嘛,用起来很方便,但是你可知道vector不仅仅是动态数组,它还可以是队列/优先队列,栈?
Vector变成队列和栈的关键函数
- erase
你会不会感到很疑惑?删除函数有什么了不起的?竟然还能玩出花样?
君莫急,且看:
vector<int>V;
V.push_back(1);
V.push_back(2);
V.push_back(3);
V.push_back(4);
对于栈很简单,使用:
V.erase(--V.end());
V.erase(V.rbegin());//与上面等价!
V.pop_back();
这就完成了删除最后一个元素操作!
立即推,vector等于stack,所以完全没必要去熟悉stack容器!
- erase变队列
V.erase(V.begin());
这样就实现了删除第一个元素,这就是vector版的队列!!
至于优先队列(自定义排序顺序),可以在所有元素进入vector以后使用sort函数自定义cmp,然后实现优先队列(效率相同!!)
sort(V.begin(),V.end(),cmp);
//cmp为自定义比较关系
+
- Vector变双端队列
V.insert(V.begin,1);
这样就在最前面插入了元素1,通过以上操作
vector在保持动态数组的同时 还是队列,双端队列,栈,优先队列!
除此之外,还有冷门Vector用法!!!!!
1.更方便的判等!
vector<int.>V1,V2;
if(V1==V2) printf(“Yes”);
else printf(“No”);
两个Vector之间可以直接用==进行判等,只有存储的元素完全相同的时候才会true
2.更方便的判断元素大小
if(V1<V2)printf("Yes");
如:
V1:1 2 2 4
V2:1 2 3 1
那么V1<V2就是true
作用:在题目要求出现不唯一的答案时,按小序列输出,通过利用sort函数可以对vector大小可以排序,然后输出第一个即可!
2.map的高级玩法**
- 用来对数字进行排序,效率无敌快!
比如:
int val;
map<int,int>Ma;
for(int i=0;i<N;i++
{
scanf("%d",&val);
Ma[val]++;
}
//这样得到的map就是有序系列,可以直接输出!!
for(auto it=Ma.begin();it!=Ma.end();it+){
for(int j=0;j<it->second;j++){
printf(" %d",it->first);
}
}
强不强!!这样排序的效率远超过了set/underorder_set!!!
利用second值也可以避免重复!!!
一举两得,非常棒!!!
- Map用来哈希映射字符串
map<string,int>Ma;
map<int,string>Mb;
string s;
int index =1;
for(int i=0;i<N;i++){
cin>>s;
if(Ma[s]!=0)continue;//0不存数据,下标从1开始,已经映射过的就跳过,不再映射。
Ma[s]=index;
Mb[index]=s;
index++;
}
这样就把string变成了int,访问直存直取,效率无敌!!!
3.字符串string的玩法~
1.find函数
find既可以找单个字符,也可以找 字符串
如:
除此之外,还有另外的几个find函数:
看名字就能懂他们的作用
rfind是find的逆序,find是从前往后,rfind就是从后往前找
string最优秀的是操作方便,可以直接用+进行连接,在很多题目中用起来简直舒服到爆,比如2018年真题中的运算树,递归遍历,string控制输出格式太好用了。
再比如1088题:1088 Rational Arithmetic (20分)
#include<vector>
#include<iostream>
#include<math.h>
#include<string>
#include<algorithm>
#include<string>
using namespace std;
long long gcd(long long a, long long b) {
if (b == 0) return a;
else return gcd(b, a%b);
}
string simple(long long a, long long b) {
string ans;
if ((a > 0 && b < 0) || (a < 0 && b>0))ans = "-";
a = abs(a);
b = abs(b);
if (a == 0)return "0";
if (b == 0)return "Inf";
long long t = gcd(a, b);
a /= t;
b /= t;
long long z = a / b;
a -= z * b;
if (z > 0 && a > 0) {
ans += to_string(z) + " " + to_string(a) + "/" + to_string(b);
}
else if (z > 0) {
ans += to_string(z);
}
else {
ans += to_string(a) + "/" + to_string(b);
}
if (ans[0] == '-')return "(" + ans + ")"
else return ans;
}
int main() {;
long long a1, a2, b1, b2;
scanf("%lld/%lld %lld/%lld", &a1, &a2, &b1, &b2);
string s1 = simple(a1, a2);
string s2 = simple(b1, b2);
printf("%s + %s = %s\n", s1.c_str(), s2.c_str(), simple(a1*b2 + b1 * a2, a2*b2).c_str());
printf("%s - %s = %s\n", s1.c_str(), s2.c_str(), simple(a1*b2 - b1 * a2, a2*b2).c_str());
printf("%s * %s = %s\n", s1.c_str(), s2.c_str(), simple(a1*b1, a2*b2).c_str());
if(abs(b1)==0)printf("%s / %s = Inf\n", s1.c_str(), s2.c_str());
else printf("%s / %s = %s\n", s1.c_str(), s2.c_str(), simple(a1*b2, a2*b1).c_str());
return 0;
}
近几年每次基本上都要考一个 字符串运用的题目。
近几年的大趋势是模板题越来越少了,以前很多题目都是固定套路,后面的题目反而简单,虽然看起来复杂一些。
近几年题目基本上都是给你一个概念, 让你读题理解,然后再利用已知知识去自由发挥emm,所以背解题模板没有用,背代码也没有用,只有通过自己不断的去理解各种知识,真正掌握熟练了才是王道。