目录
常用模板【不是和知识点一一对应的,因为有的知识点没有模板】:
知识点常考:【按照优先级:多->少】
①前缀和数组和差分数组
②递归和递推【能用for循环就别用其他循环和递归】
③排序算法:【sort()】,贪心的思想:局部最优
④二分查找,二分答案
⑤暴力搜索【bfs和dfs】[bfs多练题就好,dfs多练题+看运气,因为dfs可能超时]
⑥记忆化的【bfs和dfs】,也叫动态规划【dp】,将前面算出来或者遍历出来的值存起来,后面需要用的时候直接用,不用找了【难】
常用模板【不是和知识点一一对应的,因为有的知识点没有模板】:
cpp
1.冒泡排序:【如果第一趟排序没有发生元素位置的交换,说明这个数组的元素是有序的】【时间复杂度O(n²)】
void sort(vector<int>& stones){
for(int i=0;i<stones.size()-1;i++){
int temp=10000;
for(int j=0;j<stones.size()-1-i;j++){
if(stones[j]>stones[j+1]){
temp=stones[j];
stones[j]=stones[j+1];
stones[j+1]=temp;
}
}
if(temp==10000) break;//标记一下temp,如果第一轮时temp没有被赋值,说明数组原本就是有序的,所以不需要再排序了,可以直接输出。
}
}
2.插入排序:【时间复杂度O(n²)】
void crsort(vector<int>& a){
for(int i=1;i<a.size();i++){
if(a[i]<a[i-1]){
int temp=a[i];
int j=0;
for(j=i-1;j>=0;j--){
if(a[j]>temp) a[j+1]=a[j];
if(a[j]<=temp){
a[j+1]=temp;
break;
}
}
if(j==-1) a[0]=temp;
}
}
}
3.归并排序【时间复杂度为O(nlogn)的算法(时间复杂度相当于最小了)】
class Solution {
void gb(vector<int>& a,int left,int mid,int right){
int n1=mid-left+1;
int n2=right-(mid+1)+1;
int temp[n1+n2];
for(int i=0;i<n1;i++){
temp[i]=a[left+i];
}
for(int j=0;j<n2;j++){
temp[n1+j]=a[mid+1+j];
}
int i=0,j=n1,k=left;
while(i<n1 && j<n1+n2){
if(temp[i]<=temp[j]) a[k++]=temp[i++];
else a[k++]=temp[j++];
}
while(i<n1) a[k++]=temp[i++];
while(j<n1+n2) a[k++]=temp[j++];
}
void gbsort(vector<int>& a,int left,int right){
if(left>=right) return;
int mid=left+(right-left)/2;
gbsort(a,left,mid);
gbsort(a,mid+1,right);
gb(a,left,mid,right);
}
public:
vector<int> sortArray(vector<int>& nums) {
gbsort(nums,0,nums.size()-1);
return nums;
}
};
4.快速排序【时间复杂度O(nlogn)】
//过程模拟:
// l r
// 1 3 5 3 2 8
// i j
class Solution {
void swap(int& x,int& y){
int a=0;
a=x;
x=y;
y=a;
}
int mid_yuansu(vector<int>& a,int l,int r){
int ret=l+(rand()%(r-l+1));
int x=a[ret];
swap(a[l],a[ret]);
int i=l,j=r;
while(i<j){
while(i<j && a[j]>x) j--;
if(i<j) swap(a[i],a[j]),i++;
while(i<j && a[i]<x) i++;
if(i<j) swap(a[i],a[j]),j--;
}
a[i]=x;
return i;
}
void kssort(vector<int>& a,int l,int r){
if(l>=r) return;
int mid=mid_yuansu(a,l,r);
kssort(a,l,mid-1);
kssort(a,mid+1,r);
}
public:
vector<int> sortArray(vector<int>& nums) {
kssort(nums,0,nums.size()-1);
return nums;
}
};
5.深度优先搜索:【dfs】
bool zhao[N];
bool dfs(int a,int b){
if(a==b) return true;
else zhao[a]=true;
for(int i=0;i<w[a].size();i++){
if(!zhao[w[a][i]] && dfs(w[a][i],b)){
return true;
}
}
return false;
}
6.清理残留的脏数据,避免影响下一次的查找
memset(zhao,0,sizeof(zhao)); //查完一次后清除zhao[N]中的所有true和false,让他们都初始化为0,避免影响下一次的查找
7.二分查找算法模板:
a[mid]第一个 ≥ x 的数(左边界)【判断语句后是r=mid,所以mid=l+(r-l)/2】【不需要+1】
while (l < r) {
int mid = l + (r - l) / 2; // 不加1
if (a[mid] >= x) r = mid;
else l = mid + 1;
}
a[mid] 最后一个 ≤ x 的数(右边界)【判断语句后是l=mid,所以mid=l+(r-l+1)/2】【需要+1】
while (l < r) {
int mid = l + (r - l + 1) / 2; // 必须+1
if (a[mid] <= x) l = mid;
else r = mid - 1;
}
8.判断一个数是否是质数的模板 【埃式筛选法+欧拉进阶法】
例题:求第2025个质数
#include<bits/stdc++.h>
using namespace std;
const long long N=1e5;
bool is_zhishu[N];
vector<long long> zhishus;
long long ret;
void shi(long long n){//判断一个数是否是质数的模板 【埃式筛选法+欧拉进阶法】
memset(is_zhishu,true,sizeof(is_zhishu));
is_zhishu[0]=false;
is_zhishu[1]=false;
for(long long i=2;i<=n;i++){
if(is_zhishu[i]) zhishus.push_back(i);
if(zhishus.size()==2025){//如果此时已经有2025个质数了,就输出zhishus[2024],数组的下标从0开始
ret=zhishus[2024];
break;
}
for(long long j=0;j<zhishus.size() && i*zhishus[j]<=n;j++){//欧拉进阶法【这个循环没有也能执行,多这个循环可以让时间复杂度:O( nlog(logn) )->O(n)】
is_zhishu[i*zhishus[j]]=false;
if(i%zhishus[j]==0) break;
}
}
}
int main(){
long long n=1e5;
shi(n);
cout<<ret;
return 0;
}
9.洛谷1551亲戚【并查集模板题】【并查集函数: 合并函数:merge(x,y);查找函数:finds(x)】
#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
const int N=1e4+10;
long long fa[N];
long long finds(long long y){//找y的根节点
if(fa[y]==y) return y;
else return fa[y]=finds(fa[y]);
}
void merge(long long x,long long y){//让x的根节点变成y的(根节点)
fa[finds(x)]=finds(y);
}
int main(){
cin>>n>>m>>p;
for(long long i=1;i<=n;i++) fa[i]=i;
for(long long i=1;i<=m;i++){
long long a=0,b=0;
cin>>a>>b;
merge(a,b);
}
for(long long i=1;i<=p;i++){
long long a=0,b=0;cin>>a>>b;
if( finds(a)==finds(b) ) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
10.判断一个数是不是2的次方:
bool cifang_2(long long n){
return (n>0 && (n&(n-1))==0);
}
当返回值为true是2的次方,返回false不是2的次方