C++:算法竞赛常用库函数
秉持着奥卡姆剃刀:如无必要,勿增新知的原则, 本篇只收录使用频率高的内容。
更新
transform转换大小写
transform(word.begin(), word.end(), word.begin(), ::tolower);
对string转换成小写
transform(word.begin(),word.end(),word.begin(),::toupper);
对string转换成大写
STL
迭代器基础使用
set<int>a = {4,2,3,1,5};
for(set<int>::iterator it = a.begin();it!=a.end();it++){
cout << *it << ''; // 1 2 3 4 5
}
auto神器
编译器自行判断用户定义的变量类型
//第一种遍历方式
set<int>a = {4,2,3,1,5};
for(auto it = a.begin();it!=a.end();it++){
cout << *it << ' ';
}
//第二种,如果容器封装了begin和end就可以用,普通数组也可以
for(auto x : a){
cout << x << endl;
}
Lambda语法
格式: [] () -> return_type {}
如下场景会用就行。
int arr[5] = {3,4,1,2,7};
sort(arr,arr+5,[](int a, int b){
return a>b;
});
vector
- 常见声明:
vector<int> v1;
vector<int> v2(5);
长度为5,其实第二个参数可以传入初始值vector<int> v4 = {4, 5, 6, 7};
- 访问
- 下标访问
- 遍历:
- 普通for
- 迭代器
for(auto x : v)
- 插入push_back 弹出 pop_back
- 其它
- size
- clear O(1)
- empty
- front 返回引用类型,可以修改值 --
v.front() = 1;
- back 返回引用类型,可以修改值
erase(v.begin()+1,v.begin()+4);
删除[1,4)resize(size,default_value)
- 重写了比较运算符,机制类似字符串
string
形式上是字符串,功能上如同 vector<char>
,支持+=和+,支持cin,cout
- 声明
- string s1;
- string s2 = "123"; 也可以直接传入一个char[]
- 访问:同vector
- 用法:
- push_back pop_back
- size,length相同
- clear empty begin end
- 运算符+ += : 尾部拼接一个字符串
- 常量:string::npos:无穷大,表示无或者不存在
- str1.compare(str2);
str1.insert(begin_index,str2);
str1.erase(begin_index,length)
- c_str 转成 char*字符串
find函数
时间复杂度 O(N)
用于从前往后查找子串或者字符串第一次出现的下标位置,若找到则返回stirng::npos,与其相对的从后往前找的是rfind函数。
string s = "abcdef";
cout << s.find('a') << endl; // 0
//从下标3开始找
if(s.find('a',3) == string::npos) cout << "not found! " << endl; // not found!
cout << s.find("bc") << endl; // 1
substr
O(N)
返回子串
string str = s.substr(begin_index);
s.substr(begin_index,length);
s.substr(begin_index,-1);
表示长度为无穷,或者改成string::npos
replace
O(1) 返回替换后的结果
s.replace(begin_index,length,string content);
将指定位置子串替换成成新的结果,长度没限制。s.replace(begin_index,length,be_copyed,copyed_begin,copyed_length,)
s.replace(begin_index,legnth,num,char content)
替换成num个char字符
sstream头文件 stringstream
学校的普通题挺好用的,竞赛可能就不太行,速度慢。
斯坦福CS106L第一节课就是讲的这个,可惜后面没听了。
#include <bits/stdc++.h>
using namespace std;
int main(){
string str = "what are you doing now",sub;
stringstream ss1(str);
while(ss1 >> sub){
cout << sub << endl;
}
/*
what
are
you
doing
now
*/
str = "123 45.6";
stringstream ss2;
ss2 << str;
int x;
double y;
ss2 >> x >> y;
cout << "x = " << x << "y = " << y;
return 0;
}
其它操作
- int,long long, double 转字符串: to_string(int);
- string类型转成int 类型 : stoi("123456");
- 还有stol stof stoll等
- 整行读取
while(getline(cin,s)){cout << s << endl;}
stack
- 没有clear,只能暴力pop
- 养成习惯,先判断不为空再pop
priority_queue 堆
- 声明
priority_queue<int> heap;
大顶堆priority_queue<int, vector<int>, greater<int> > heap1;
// 小顶堆
- 访问方式:只能top,返回的是堆顶元素的引用。
- 结构体:
#include <bits/stdc++.h>
using namespace std;
struct pii{
int x;
//比较谁的优先级小
bool operator< (const pii& j)const{ // 语法,两个const
if(this->x > j.x) return true; // 越大优先级越小,那就是小根堆
return false;
}
};
int main(){
priority_queue<pii>heap;
heap.push({.x=100});
heap.push({.x=200});
cout << heap.top().x << endl;
return 0;
}
pair
- 排序先比较first,如果不一样再看second
- 声明:
- pair<int,string>p = {3,"haha"};
- 访问:
- 点运算符,.first,.second
- 赋值:
- p = make_pair(3,"123456");
set
集合,内部元素唯一和自动排序,底层是红黑树。
插入O(LogN) 插入
- 声明:
set<int> ass2 = {3, 4, 2, 3};
set<int> ass1;
- 遍历:auto
- 常用函数:
insert(value);
- 返回一个pair,
if (ass.insert(3).second == false) {失败}
- 返回一个pair,
erase(value/iterator)
- size empty count(可以用来确定某个元素是否存在)
- clear O(N)
- lower_bound
- O(logn)的时间复杂度内第一个大于等于指定元素的迭代器,找不到返回end()
- O(logn)的时间复杂度内第一个大于指定元素的迭代器,找不到返回end()
- find() 返回查找元素的迭代器,找不到返回end()
unordered_set
存放元素,不会排序。底层时哈希。速度更快一点。
multiset
可以重复,不如map
map
关联容器。底层是红黑树。根据first排序。插入查找修改复杂度都是O(logN)
- 初始化
- map<double, long long> mp1;
- 插入
- mp.insert({"222", 5});
- mp["222"] = 5; 如果key存在,修改其value值,否则插入
- 访问
- 单个:mp["222"],记得判断其是否存在,用count
- 遍历:auto就行了,然后x.first x.second
- 常见函数
- erase(key/iterator); 成功返回1,否则返回0
- 其它跟set基本一样
unordered_map
当hashmap用
deque
双端队列,支持头部尾部的插入和删除,效率比vector低。
list
双向链表,不支持随机访问,支持头部尾部的插入和删除
- 声明
- list
l2(length,default_value);
- list
- 函数
- insert(iterator,val);
- sort(); 升序排序
- reverse(); 翻转,学校的小题挺好用的。
- merge(list2) :用第二个有序的 list 合并一个有序 list
- erase(iterator):删除iterator,返回删除前的下一个的迭代器
- erase(iterator_start, iterator_end):删除[iterator_start, iterator_end)范围内的元素,返回删除前的iterator_end
- splice(list.iterator, list2, list2.iterator_start, list2.iterator_end):在本list的 iterator后插入list2的从 iterator_start 到 iterator_end, 后面两个可填可以不填,当填了iterator_start,可不填最后一个,时间复杂度O(1)
Algorithm库
sort
- 形式1:sort(arr,arr+10); 范围[0,10)
- 形式2:sort(arr+1,arr+9,cmp);
bool cmp(int a,int b){return a>b;}
- cmp可以是封装好的
greater<int>()
- cmp可以是封装好的
- 形式3:lambda
reverse
翻转,传参和sort一样
lower_bound upper_bound
O(logN)
lower_bound(vt.begin(), vt.end(), value);
可以自己二分实现。
unique
用于将去除一个有序序列中指定范围内的重复元素(实际没有去除),返回去除后的尾指针
一般这么玩:
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
next_permutation
生成全排列,结果是排序的
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> v = {1,2,3,4};
do{
for(int i=0;i<v.size();i++){
cout << v[i];
}
cout << endl;
}while(next_permutation(v.begin(),v.end()));
}
find
暴力查找一个序列中指定范围内的某个值第一次出现的位置,返回其位置的指针
O(N)
random_shuffle
随机打乱给定范围的序列
参考文章
{% link 一位ACM大佬的总结, https://blog.csdn.net/hao_6_6/article/details/118612536, https://g.csdnimg.cn/static/logo/favicon32.ico %}
- 感谢你赐予我前进的力量