string转换成int
string str = "123";
int n = atoi(str.c_str());
cout<<n; //123
vector二维排序
vector格式为[[1,3],[2,2],[3,1]],从大到小排序结果为:
sort(vec.begin(), vec.end(),
[&](const vector<int> &a, const vector<int> &b){
return a[1]>b[1];});
判断a字符串是否包含b字符串
判断a字符串是否包含b字符串
if(a.find(b)!=string::npos){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
一次遍历找第二大的数
int max1 = -1;
int max2 = -1;
for(auto x : vec){
if(x > max1){
max2 = max1;
max1 = x;
}
else if(x>max2 && x<max1)
{
max2 = x;
}
}
return max2;
二分
1. 左闭右开
int search(vector<int>& nums, int target) {
int left = 0;
// 定义target在左闭右开的区间里,即:[left, right)
int right = nums.size();
//因为left==right的时候,在[left,right)是无效
//的空间,所以使用<
while (left < right) {
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
// target 在左区间,在[left, middle)中
right = middle;
} else if (nums[middle] < target) {
// target 在右区间,在[middle + 1, right)中
left = middle + 1;
} else { // nums[middle] == target
return middle;
}
}
// 未找到目标值
return -1;
}
2. 左闭右闭
int search(vector<int>& nums, int target) {
int left = 0;
//定义target在左闭右闭的区间里,[left, right]
int right = nums.size() - 1;
//当left==right,区间[left,right]依然有效,所以用<=
while (left <= right) {
// 防止溢出 等同于(left + right)/2
int middle = left + ((right - left) / 2);
if (nums[middle] > target) {
// target 在左区间,所以[left, middle-1]
right = middle - 1;
} else if (nums[middle] < target) {
// target 在右区间,所以[middle+1,right]
left = middle + 1;
} else { // nums[middle] == target
// 数组中找到目标值,直接返回下标
return middle;
}
}
// 未找到目标值
return -1;
}
二叉树
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
如果要搜索其中一条符合条件的路径,那么递归需要返回值
if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;
如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值
left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;
遍历map
//方法一
for(auto i=map.begin();i!=map.end();i++){}
//方法二
for(auto& [_, v] : map)//(遍历value)
for(auto& [k, v] : map)//(遍历key,value)
map对value排序
vector<pair<int, int>> vec;
for (auto i = map.begin(); i != map.end(); i++)
vec.push_back(make_pair(i->first, i->second));
sort(vec.begin(), vec.end(),
[](const pair<int, int> &x,
const pair<int, int> &y)
-> int {
return x.second < y.second;
});
移除k个数,使数字最小
k次扫描,找第一个比后面大的字符删除
可以使用栈或者二重循环
判断两数是否互质(最大公因数为1)
if (gcd(i, j) != 1)
continue;不互质则跳过
判断质数
bool isPrime(int n)
{
if(n==1)
return false;
if(n<=3)
return true;
int i;
for(i=2;i<=sqrt(n);i++)
if(n%i==0)
break;
if(i>sqrt(n))
return true;
return false;
}
优先级队列
小顶堆
priority_queue <int,vector<int>,greater<int> > q;
大顶堆
priority_queue <int,vector<int> > q;
回溯带有判断条件
//right
for(int i = index; i <= n; i++){
if(A){
push_back();
dfs()
pop_back();
}
if(B){
push_back();
dfs()
pop_back();
}
}
//error
for(int i = index; i <= n; i++){
if(A)
push_back();
if(B)
push_back();
dfs()
if(A)
pop_back();
if(B)
pop_back();
}
组合问题(每个元素在每个组合中只能使用一次)
for循环每次从startIndex开始遍历,下一层搜索要从i+1开始
void backtracking(int n, int k, int startIndex){
if(终止条件){}
for (int i = startIndex; i < n; i++){
backtracking(n, k, i + 1);//回溯
}
}
组合总和(每个元素都可以无限制重复被选取)
for循环每次从startIndex开始遍历,下一层搜索仍然为i,不用i+1了,表示可以重复读取当前的数
void backtracking(int n, int k, int startIndex){
if(终止条件){}
for (int i = startIndex; i < n; i++){
backtracking(n, k, i);//回溯
}
}
组合总和2(每个元素在每个组合中只能使用一次,但集合包含重复元素)
集合有重复元素,但还不能有重复的组合
要对同一树层使用过的元素进行跳过
if (i>0 && nums[i]==nums[i-1] && used[i-1]==false)
{
continue;
}
全排列
排列问题,每次都要从头开始搜索,要从0开始而不是startIndex。
因此也需要记录哪些元素已经被使用
for (int i = 0; i < nums.size(); i++) {
// path里已经收录的元素,直接跳过
if (used[i] == true)
continue;
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
全排列 II(集合包含重复元素,去重)
要对同一树层使用过的元素进行跳过
//加在for循环中
if (i>0 && nums[i]==nums[i-1] && used[i-1]==false)
{
continue;
}
进制转换
将一个十进制数,转换为N进制数,通用公式:就是用该十进制数对N取模,并令该十进制数等于该数对N取余的结果。结果取反后即为答案
求多个区间的最大重合数量
会议室2
会议室2,可输出区间
生存人数:在会议室的基础上记录下标
检测循环依赖,拓扑排序
选择图中一个入度为0的点,记录下来
在图中删除该点和所有以它为起点的边
重复1和2,直到图为空或没有入度为0的点。
并查集
递归算法的时间复杂度
时间复杂度:递归的总次数*每次递归的数量
空间复杂度:递归的深度*每次递归创建变量的个数