大学算法类竞赛的常用模板【自己总结+收录的】【c++版】

目录

知识点常考:【按照优先级:多->少】

常用模板【不是和知识点一一对应的,因为有的知识点没有模板】:


知识点常考:【按照优先级:多->少】

①前缀和数组和差分数组

②递归和递推【能用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的次方
相关推荐
码云数智-大飞2 小时前
分布式锁的“双雄对决”:Redis 与 ZooKeeper 的深度博弈与选型指南
算法
cpp_25012 小时前
P1910 L 国的战斗之间谍
数据结构·c++·算法·题解·洛谷·背包dp
yu85939582 小时前
时延估计的互相关算法(MATLAB实现)
开发语言·算法·matlab
逸风尊者2 小时前
2026 主流 Claw 类产品技术报告
人工智能·后端·算法
楼田莉子2 小时前
同步/异步日志系统:工具类以及日志的简单模块
linux·服务器·数据结构·c++
强盛机器学习~2 小时前
考虑异常天气和太阳辐射下基于强化学习的无人机三维路径规划
算法·matlab·无人机·强化学习·路径规划·无人机路径规划·q-learning
Pixlout2 小时前
《7元接口体系》v1.0
网络·算法·硬件工程
SUNNY_SHUN2 小时前
不需要Memory Bank:CMDR-IAD用2D+3D双分支重建做工业异常检测,MVTec 3D 97.3%
论文阅读·人工智能·算法·3d
Matlab光学3 小时前
Matlab 复现:分数阶&整数阶OAM 变换
算法·matlab·拓扑学