蓝桥杯常考算法与方法集锦

#include <memory.h><string.h>
void *memset(void *s, int ch, size_t n);
#include <algorithm>
 
sort(a,a+n)排序函数,从小到大,a为数组名字,n为元素个数
 
sort(vector.begin(),vector.end())排序vector
 
只要数据类型定义了小于操作符,即可用sort
 
sort(a,a+n,compare)即可按照自定义顺序排列,compare为比较函数,返回值为bool
 
lower_bound(a,a+n,x)二分查找,查找大于或等于x的第一个位置,只能查找vector<>数组,返回值为vector<>::iterator指针
 
    unique(vector1.begin(),vector1.end()),重排元素,使得所有值提前,返回值为重排后最后一个非重复值的后面的值的迭代器,即从返回值到vector1.end()是无意义的值,也是重复值的总数量
 
reverse(vector1.begin(),vector1.end()),反转元素顺序
 
next_permutation(p,p+n),求下一个全排列,枚举用
#include <vector>   数组
 
定义示例:vector<int> b(5);或者vector<int> a;
 
赋值:b[0]=1;只有第一种定义可以这样赋值
 
函数:
 
int size(),获取大小
 
void resize(int num),改变大小
 
void push_back(int x),向尾部添加元素
 
void pop_back(),删除最后一个元素
 
void clear(),清空
 
bool empty(),检查是否为空
 
iterator insert(iterator x,y),向vector数组的x位置插入元素y,x可以为v.begin()+2
 
iterator erase(iterator x),删除vector数组的x位置元素
 
iterator begin(),返回头指针
 
iterator end(),返回尾指针
 
vector<>::iterator为一个可以指向其元素的指针
#include <set>      
集合,其中不含重复元素,且其中元素已从小到大排序,从1开始
 
定义示例:set<int> a;
 
函数:
 
int size(),获取大小
iterator find(x),若找到x,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置,即s.end()
void clear(),清空
bool empty(),检查是否为空
iterator insert(y),向set集合插入元素y
iterator erase(iterator x),删除set集合的值为x的元素,返回值为下一个位置的迭代器
iterator begin(),返回头指针
iterator end(),返回尾指针
set<>::iterator为一个可以指向其元素的指针
#include <map>       映射,索引
 
定义示例:map<string,int> month_name;
 
赋值:map[“July”]=7;
 
函数:
 
iterator find(y),寻找索引值为y的元素,返回指向其的指针
 
iterator insert(map<string,int>(“July”,7)),向map映射插入元素(“July”,7)
 
iterator erase(iterator x),删除map映射的迭代器x的元素
 
map< string,int>::iterator l_it;;
 
   l_it=m.find(“July”);
 
   if(l_it==m.end())
 
        cout<<"we do not find July"<<endl;
 
   else  m.erase(l_it);  //delete July;
 
iterator begin(),返回头指针
 
iterator end(),返回尾指针
 
map<>::iterator为一个可以指向其元素的指针
#include <stack>
 
定义示例:stack<int> s;
 
void push(x),将值x压入栈
 
void pop(),删除顶部元素
 
top(),获得栈顶元素,但不删除
 
bool empty(),检查是否为空
 
int size(),获取大小
#include <queue>
 
定义示例:queue<int> q;
 
void push(x),将值x入队
 
void pop(),出队
 
front(),获得队头元素,但不删除
 
bool empty(),检查是否为空
 
int size(),获取大小
#include <string>
 
string substr(int pos = 0,int n = npos) const;  //返回pos开始的n个字符组成的字符串
 
void swap(string &s2);                                       //交换当前字符串与s2的值
 
string &insert(int p0, const char *s);                //在p0位置插入字符串
 
string &erase(int pos = 0, int n = npos);          //删除pos开始的n个字符,返回修改后的字符串
 
int find(char c, int pos = 0) const;                     //从pos开始查找字符c在当前字符串的位置
 
int find(const char *s,int pos = 0) const;         //从pos开始查找字符串s在当前串中的位置

算法:

快速排序:
 
void quicksort(int *a,int l,int r){
 
         if(l>=r)
 
                  return;
 
         int temp=a[l];                                    //哨兵
 
         int i=l,j=r;
 
         while(i<j){
 
                  while(i<j){                                   //从右开始往左判断
 
                          if(a[j]>=temp){
 
                                   j--;
 
                          }
 
                          else{
 
                                   a[i++]=a[j];
 
                                   break;
 
                          }
 
                  }
 
                  while(i<j){                                   //从左开始往右判断
                          if(a[i]<=temp){
                                   i++;
                          }
                          else{
                                   a[j--]=a[i];
                                   break;
                          }
                  }
         }
         a[i]=temp;                                          //将哨兵放回中间位置
         quicksort(a,l,i-1);                               //左边排序
         quicksort(a,i+1,r);                             //右边排序

归并排序:
 
void mergesort(int *a,int l,int r,int *b){
 
         if(l>=r)
                  return ;
 
         int mid=l+r;
 
         mid/=2;
 
         mergesort(a,l,mid,b);      //左边有序
 
         mergesort(a,mid+1,r,b);  //右边有序
 

         int k=l,i=l,j=mid+1;                    //注意k的初值
 
         while(i<=mid&&j<=r){              //将i-mid和j-r两组有序序列,归并在一个有序序列中
 
                  if(a[i]<=a[j])
 
                          b[k++]=a[i++];
 
                  else
 
                          b[k++]=a[j++];
 
         }
 
         while(i<=mid)                            //将i-mid剩余的数放在最后
 
                  b[k++]=a[i++];
 
         while(j<=r)                                 //将j-r剩余的数放在最后
 
                  b[k++]=a[j++];
 
         for(k=l;k<=r;k++)                       //将b数组中的数据拷贝到原数组中
 
                  a[k]=b[k];
 
}
并查集:
 
#define N 100
 
int father[N];
 
void init() {
 
    for(int i=0; i<N; i++)
      father[i] = i;
}
// 合并两个元素所在的集合
void union(int x,int y) {
    x = getfather(x);
    y = getfather(y);
    if(x!= y)
       father[x]=y;
}
// 判断两个元素是否属于同一个集合
bool same(int x,int y) {
    return getfather(x)==getfather(y);
}
// 获取根结点
int getfather(int x) {
    while(x != father[x])
      x = father[x];
    return x;
}
// 获取根结点,是上边函数的改进,压缩了路径长度
int getfather(int x) {
    if(x != father[x])
      father[x] = getfather(father[x]); // 路径压缩修改的是father数组
    return father[x];
}
二分查找:
 
int binary_search(int *a,int l,int r,int v){        //a为待查找数组,l为下界下标,r为上界下标,v为目标值
 
         int mid;
 
         while(l<=r){
 
                  mid=l+r;
 
                  mid/=2;
 
                  if(a[mid]==v)   return mid;
 
                  else if(a[mid]>v)      r=mid-1;
 
                  else  l=mid+1;
 
         }      
 
         return -1;
 
}
01背包动态规划:
 
int f[5000];
 
int v[201],w[201];
 
int main(int argc, char** argv) {
 
         int n=0,m,i,j,mx=0;
 
         cin>>n>>m;
 
         for(i=1;i<=n;i++){
 
                  cin>>w[i]>>v[i];
 
         }
 
         for(i=1;i<=n;i++){
 
                  for(j=m;j>=w[i];j--){
 
                          f[j]=max(f[j],f[j-w[i]]+v[i]);
 
                          mx=max(mx,f[j]);
 
                  }
 
         }
 
         cout<<mx;
         return 0;
}
LIS最长上升子序列
 
int LIS(int *a,int n){
 
         int *dp=new int[n];         //存储以i为尾的最长上升子序列长度
 
         int mx=0,m,i,j;
 
         dp[0]=1;                            //初值,第一个字符为1
 
         for(i=1;i<n;i++){
 
                  m=0;
 
                  for(j=0;j<i;j++){        //对当前i之前的所有元素的最长上升子序列做判断
 
                          if(dp[j]>m&&a[j]<a[i]){
                                   m=dp[j];
                          }
                  }
                  dp[i]=m+1;               //最大m值再加上1
                  mx=max(mx,dp[i]); //同时判断所有最长上升子序列长度的最大值
         }
         return mx;
}
LCS最长公共子序列
 
动态规划法:
 
void LCS(string str1,string str2)
 
{
 
         int x_len = str1.length();
 
         int y_len = str2.length();
 
        
 
         int arr[50][50] = {{0,0}};
 
        
 
         int i = 0;
 
         int j = 0;
 
         //动态规划二维矩阵
 
         for(i = 1; i <= x_len; i++)
         {
                  for(j = 1; j <= y_len; j++)
                  {
                          if(str1[i - 1] == str2[j - 1])
                          {
                                   arr[i][j] = arr[i - 1][j - 1] + 1;
                         }
                          else
                          {
                                   if(arr[i][j - 1] >= arr[i - 1][j])
 
                                   {
 
                                            arr[i][j] = arr[i][j - 1];
 
                                   }
 
                                   else
 
                                  {
 
                                            arr[i][j] = arr[i -1][j];
 
                                   }
 
                          }
 
                  }
 
         }
 
        
 
         //打印最长公共子序列
 
         stack<char> s;
 
        
 
         for(i = x_len, j = y_len; i >= 1 && j >= 1;)
 
         {
 
                  if(str1[i - 1] == str2[j - 1])
 
                  {
 
                          s.push(str1[i - 1]);
 
                          //cout<<str1[i - 1]<<" ";
                          i--;
                          j--;
                  }
                  else
                  {
                          //  if(arr[i][j -1] >= arr[i - 1][j])//打印两种情况
 
                          if(arr[i][j -1] > arr[i - 1][j])
 
                          {
 
                                   j--;
 
                          }
 
                          else
 
                          {
 
                                   i--;
 
                          }
 
                  }
 
         }
 
         while(!s.empty()){
 
                  cout<<s.top();
                  s.pop();
         }
         cout << endl;
}


递归法:(只能求数量)
int LCS(char* x,char *y){
         if(strlen(x)==0)                  return 0;
         if(strlen(y)==0)         return 0;
        
         if(*x==*y)         return LCS(x+1,y+1)+1;
         return max(LCS(x,y+1),LCS(x+1,y));
}
Dijkstra  最短路径算法
 
#define MAX 9999999
 
#define NUM 6
 
int edge[NUM][NUM];                     //存储两点间距离
 
int dist[NUM];                                   //存储到每个点的最短距离
 
int mark[NUM];                                 //标记是否已选
 
//n:多少个点  start:起始点   
 
void Dijkstra(int n,int start){
 
         int i,j,k=start;
 
         int min;
 
         for(i=0;i<n;i++){
                  mark[i]=0;
                  dist[i]=edge[start][i];
         }
         mark[start]=1;
         dist[start]=0;
         for(i=0;i<n;i++){
                  min=MAX;
                  for(j=0;j<n;j++){
                          if(!mark[j]&&dist[j]<min){
                                   min=dist[j];
                                   k=j;
                          }
                  }
                  mark[k]=1;
                  for(j=0;j<n;j++){
                          if(!mark[j]&&dist[j]>dist[k]+edge[k][j]){
 
                                   dist[j]=dist[k]+edge[k][j];
 
                          }
 
                  }
 
         }
 
}

Floyd
 
#define MAX 9999999
 
#define NUM 6
 
int edge[NUM][NUM];
 
int temp[NUM][NUM];
 
 
 
void Floyd(int a[NUM][NUM],int b[NUM][NUM]){
 
         int i,j,k;
 
         for(k=0;k<NUM;k++){
                  for(i=0;i<NUM;i++){
                          for(j=0;j<NUM;j++){
                                   if(k==0)
                                            b[i][j]=a[i][j];
                                   else{
                                            b[i][j]=min(b[i][j],b[i][k]+b[k][j]);
                                   }
                          }
                  }
         }      
}
最小生成树(prim)最好选择下边Krusal算法
 
#define MAX  100000
 
#define VNUM  6                       
 
int edge[NUM][NUM];
 
int lowcost[NUM];             //记录Vnew中每个点到V中邻接点的最短边
 
int addvnew[NUM];               //标记某点是否加入Vnew
 
int adjecent[NUM];            //记录最小生成树的边,从adjecent[i]到i
 
 
 
void prim(int start){
 
         int i,j,k;
 
         int v,min;
 
         int sum=0;
 
         for(i=0;i<NUM;i++){
 
                  addvnew[i]=0;
 
                  adjecent[i]=start;
 
                  lowcost[i]=edge[start][i];
 
         }
 
         addvnew[start]=1;
 
         for(i=0;i<NUM-1;i++){
 
                  min=MAX;
 
                  v=-1;
 
                  for(j=0;j<NUM;j++){
 
                          if(!addvnew[j]&&min>lowcost[j]){
 
                                   min=lowcost[j];
 
                                   v=j;
 
                          }
 
                  }
 
                  if(v!=-1){
 
                          addvnew[v]=1;
 
                          sum+=lowcost[v];
 
                          for(j=0;j<NUM;j++){
 
                                   if(!addvnew[j]&&lowcost[j]>edge[v][j]){
 
                                            lowcost[j]=edge[v][j];
 
                                            adjecent[j]=v;
 
                                   }
 
                          }
 
                  }
 
         }
 
}

Kruskal
 
#define N 100
 
Int w[N],p[i],r[i];     //w为权值数组,p为并查集数组,r为边权值排序数组,里边存储的是边的w对应的标号
 
Int cmp(const int I,const int j){ return w[i]<w[j]; }
Int find(int x){ return p[x]==x?x:find(p[x]); }
Int Kruskal(){
         Int ans=0;
         For(int i=0;i<n;i++) p[i]=I;
         For(int i=0;i<n;i++) r[i]=I;
         Sort(r,r+m,cmp);//给边升序排列
         For(int i=0;i<n;i++){
                  Int e=r[i]; int x=find(u[e]); int y=find(v[e]);
                  If(x!=y) { ans+=w[e]; p[x]=y; }
         }
         return ans;
}
可重集的全排列(递归)
 
void print_permutation(int n,int P[],int A[],int cur)        //P按顺序存储待排列数,A同样大小的临时空间数组
 
{
 
         int i,j;
 
         if(cur==n){
 
                  for(i=0;i<n;i++) printf("%d ",A[i]);                    //可输出可统计
                  printf("\n");
         }
         else for(i=0;i<n;i++) if(!i||P[i]!=P[i-1]){
                  int c1=0,c2=0;
                  for(j=0;j<cur;j++) if(A[j]==P[i])c1++;
                  for(j=0;j<n;j++) if(P[i]==P[j])c2++;
                  if(c1<c2){
                          A[cur]=P[i];
                          print_permutation(n,P,A,cur+1);
                  }
         }
}
next_permutation(p,p+n),求下一个全排列
二进制法求子集
 
void print_submet(int n,int s){                 //打印一个子集
 
         for(int i=0;i<n;i++)                            
                  if(s&(1<<i)) printf("%d ",i);      //s=101时,代表子集{0,2}
         printf("\n");
}

int main() {
         int n=7;                                                //代表集合{0,1,2,3,4,5,6},二进制表示
         for(int i=0;i<(1<<n);i++)                    //枚举所有子集
                  print_submet(n,i);
         return 0;
}
快速求幂
 
int pow3(int x,int n){
 
         if(n==0)                                       //任何数的0次幂都是1
 
                  return 1;
 
         else{                                            //把尾部的0全部去除
 
                  while((n&1)==0){
 
                          n>>=1;
 
                          x*=x;
 
                  }
 
         }
 
         int res=x;                                    //后边的都不明白
 
         n>>=1;
 
         while(n!=0){
 
                  x*=x;
 
                  if((n&1)!=0)
 
                          res*=x;
 
                  n>>=1;
 
         }
 
         return res;
 
}
辗转相除法求最大公约数:
 
int gcd(int a,int b){
 
         int temp;
 
         while(a%b!=0){
 
                  temp=a;
 
                  a=b;
 
                  b=temp%b;
 
         }
 
         return b;
 
}
 
辗转相除法最大公倍数:
 
int lcm(int a,int b){
 
         int a1=a,b1=b,temp;
 
         while(a%b!=0){
 
                  temp=a;
 
                  a=b;
 
                  b=temp%b;
 
         }
 
         return a1/b*b1;
}
//二进制压位 
int ans=0;
for(int i = 0;i < (1<<14);i++){
	int tot_1=0;
	int tot_0=0;
	int num = 2;
	for(int j = 0;j < 14;j++){
		if(i&(1<<j)){
			tot_1++;
			num = num*2;
		}else{
			tot_0++;
			num=num-1;
		}
	}
	if(tot_1==5&&tot_0==9&&num==1){
		ans++;
	}
} 

//01背包问题
for(int i = 1;i <= N;i++){
	for(int j = 0;j <= v;j++){
		if(j>=w[i]){
			dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
		}else{
			dp[i][j]=dp[i-1][j];
		}
	}
} 

//完全背包问题
for(int i = 1;i <= N;i++){
	for(int j = c[i];j <= v;j++){
		dp[i][j]=max(dp[i-1][j],dp[i][j-c[i]]+w[i]);
	}
}

dp[N][v];
//最长上升子序列 
int dp[MAX_N],a[MAX_N],n,ans=0;
for(int i = 1;i <= n;i++){
	dp[i]=1;
	for(int j = 1;j < i;j++){
		if(a[j]<a[i]){
			dp[i]=max(dp[i],dp[j]+1);
		}
	}
	ans=max(ans,dp[i]);
}

//最长公共子序列
char s1[MAX_N],s2[MAX_N];
int n,ans=0,lcs[MAX_N][MAX_N];
for(int i = 1;i <= n;i++){
	for(int j = 1;j <= n;j++){
		lcs[i][j]=0;
		if(s1[i]==s2[j]){
			lcs[i][j]=lcs[i-1][j-1]+1;
		}else{
			lcs[i][j]=max(lcs[i-1][j],lcs[i][j-1]);
		}
		ans=max(ans,lcs[i][j]);
	}
}

//欧几里得算法(最大公约数):辗转相除法
int gcd(int a,int b){
	if(b==0){
		return a;
	}
	return gcd(b,a%b);
} 

//最小公倍数
lcm(a,b)=(a*b)/gcd(a,b);
//质数筛选:埃氏筛选法
int n;
for(int i = 2;i <= n;i++){
	is_prime[i]=1;//初始化为质数 
}
for(int i = 2;i*i<=n;i++){
	if(is_prime[i]){
		for(int j = i*i;j<=n;j+=i){
			is_prime[j]=0;
		}
	}
}

//质数筛选法:埃氏筛选法
int n;
for(int i=2;i<=n;i++){
	is_prime[i]=0;//初始化为质数 
} 
for(int i=2;i*i<=n;i++){
	if(is_prime[i]){
		for(int j=i*i;j<=n,j+=i){
			is_prime[j]=0;
		}
	}
}


#include <algorithm> 
#include <string.h> 
#include <iostream> 
#include <stdio.h>
#include <string>
#include <vector> 
#include <queue> 
#include <map> 
#include <set> 
using namespace std; 
 
//判断闰年
int is_leap_year(int year){
	if(year%400==0 ||(year%100!=0&&year%4==0)){
		return 1;
	}
	return 0;
}
 
//二分法优化
int l=1,r=max_num;
while(l<r){
	int mid=(l+r+1)/2;
	if(cut_ok(mid)){
		l=mid;
	}else{
		r=mid-1;
	} 
} 

//暴力搜索:dfs凑算式
#include<stdio.h>
int num[10];
int ans=0;
bool visit[10];
 
void solve(){
	double sum = num[0]+(double)num[1]/num[2]+(double)(num[3]*100+num[4]*10+num[5])/(num[6]*100+num[7]*10+num[8]);
	if(sum==10){
		ans++;
	}
	void dfs(int index){
		if(index==9){
			solve();
			return;
		}
		for(int i=1;i<10;i++){
			if(!visit[i]){
				visit[i]=true;
				num[index]=i;
				dfs(index+1);
				visit[i]=false;
			}
		}
	}
	
	int main(){
		dfs(0);
		printf("%d\n",ans);
		return 0;
	}
	
} 

//快速排序
void swap(int a[],int i,int j){
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}
int partition(int a[],int p,int r){
	int i = p;
	int j = r+1;
	int x = a[p];
	while(1){
		while(i<r&&a[++i]<x);
		while(a[--j]>x);
		if(i>=j)break;
		swap(a,i,j);
	}
	swap(a,p,j);
	return j;
}
 
void quicksort(int a[],int p,int r){
	if(p<r){
		int q = partition(a,p,r);
		quicksort(a,p,q-1);
		quicksort(a,q+1,r);
	}
}

int main(){
	int a[]={5,12,65,44,2,8,62,4,3,98,14,25};
	int N=12;
	
	quicksort(a,0,N-1);
	for(int i = 0;i < N;i++){
		printf("%d ",a[i]);
	}
	printf("\n");
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

phial03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值