本人在写算法题上一直是一个不温不火的状态:基本题目可以做一做,比赛上拿不了奖的程度。
但是找工作了,面试又要写。这篇主要总结一下基础的算法和常用的一些C++方法,复习时用。
基础算法
攻略宝典:OI Wiki - OI Wiki (oi-wiki.org)
常用C++方法
通用的容器方法
// 所有容器都支持迭代器
begin() // 获取指向第一个元素的迭代器
end() // 获取指向最后一个元素后一个位置的迭代器
// 头尾元素
front() // 获取第一个元素
back() // 获取最后一个元素
// 容器大小
size() // 获取容器中元素的数量
// 插入和删除
push_back() // 在尾部插入元素
insert() // 在指定位置前插入元素
pop_back() // 删除尾部元素
erase() // 删除指定位置的元素或指定区间的元素
// 其他操作
clear() // 清空容器中的元素
empty() // 判断是否为空
vector
// 创建一个数组,最初都会使用
int a[10];
// 使用vector创建
vector<int> vec(10, 0); // 大小为10 内容为0
vector<vector<int>> vec(10, vector<int>(10,0)); // 大小为10 内容为vector
// 更改大小 对于二维需要进行循环更改
vec.resize(10, 0); // 可以同时设定初始值
// 快速填充
fill(vec.begin(), vec.end(), 0);
// 删除元素 [i,j) 含左不含右
vec.erase(vec.begin()+i, vec.begin()+j)
set & multiset
插入的元素是唯一的,多次插入仅会保留一个(使用 count() 方法只会返回 0 或 1)
multiset 与 set类似,不过可以保留多个相同元素
// set自动排序从小到大
set<int> aset;
aset.insert(1);
aset.insert(1); // 只会保留一个,但是仍以执行
aset.insert(2);
map & unordered_map
内部存储的是 pair<key, value>,默认按照key值从小到大排序
unordered_map与map不同在于不会进行排序,其他与map相同
// 声明
map<int,int> amap;
// 可以直接进行修改
amap[0] = 1;
// 返回出现的次数,判断是否存在
amap.count(k);
// 返回对应的迭代器<k,v>
amap.find(k);
// 删除map中的值,返回 0/1 表示删除了几个
amap.erase(k);
// 遍历map
for(auto [k, v]:amap){
cout <<k <<endl;
cout <<v <<endl;
}
// 遍历map
for(auto it = amap.begin(), it != amap.end(), it++){
cout <<it->first <<endl;
cout <<it->second <<endl;
}
// 获取 map 中的内容(vector 中的一种声明定义方法)
vector<pair<int, int>> avec(amap.begin(), amap.end());
stack
栈
stack<int> st; // 声明
st.top() // 返回栈顶
st.push() // 压入栈顶
st.pop() // 出栈
st.empty() // 返回是否为空
queue & deque
队列和双端队列
q.front() // 返回队首
q.back() // 返回队尾
q.push() // 入队
q.pop() // 出队
q.empty() // 返回是否为空
queue<int> myQueue;
myQueue.push(10);
// 双端队列区分 front 和 back
deque<int> myDeque;
// 插入
myDeque.push_back(100);
myDeque.push_front(200);
// 访问
int f = myDeque.front();
int b = myDeque.back();
// 删除
myDeque.pop_back();
myDeque.pop_front();
priority_queue
优先队列(堆)
priority_queue<int> pq; // 默认大顶堆
//构造一个大顶堆,堆中小于当前节点的元素需要下沉,因此使用less 默认
priority_queue<int, vector<int>, less<int>> priQueMaxFirst;
//构造一个小顶堆,堆中大于当前节点的元素需要下沉,因此使用greater
priority_queue<string, vector<string>, greater<string>> priQueMinFirst;
// 遍历
while(!pq.empty()){
cout<<pq.top()<< " ";
pq.pop();
}
_permutation全排列方法
// 返回 bool 值,是否到一个循环的末尾
next_permutation(f,f+3);
prev_permutation(f,f+3);
_bound有序序列中的二分查找方法
// 返回的是一个指针 指向所找到的目标
lower_bound() // 找出第一个大于等于的数
upper_bound() // 找出第一个大于的数
less & greater比较函数
less<T>变成升序(小的优先,从左到右遍历下标时,数组元素是从小到大)
greater<T>变成降序(大的优先,从左到右遍历下标时,数组元素是从大到小)
// 在sort中,比较函数传入的就是函数(带括号)
sort(vec.begin(),vec.end(),greater<int>());
// 在set等容器中,比较函数传入的是函数的引用(不带括号)
set<int, greater<int>>
其他知识
数据规模估计算法复杂度
根据数据规模推导解题算法:由数据范围反推算法复杂度以及算法内容 - AcWing
算法复杂度计算,c++语言1s的计算量最多 5*10^8 ,一般不考虑常数即10^8次计算
边界数值
int 可以表示的大小:2开头的10位数
INT_MAX:最大整型
INT_MIN:最小整型
ASCII对照(字符对照):0 -> 48 A -> 65 a -> 97
字符串处理
c++的字符串处理比较麻烦,这里直接放一个例题:. - 力扣(LeetCode)
class Solution {
public:
string discountPrices(string sentence, int discount) {
double d = 1 - discount / 100.0;
// 头文件 sstream
stringstream ss(sentence);
string ans, w;
while (ss >> w) { // 一边分割,一边加到答案中
if (!ans.empty()) {
ans += ' '; // 非空加空格
}
if (w.length() > 1 && w[0] == '$' && all_of(w.begin() + 1, w.end(), ::isdigit)) {
stringstream s;
// stoll 转换为long long (另外还有stol 转换为long int)
// << fixed << setprecision(2) : 格式化保留小数点后两位
s << fixed << setprecision(2) << '$' << stoll(w.substr(1)) * d;
ans += s.str();
} else {
ans += w;
}
}
return ans;
}
};