蓝桥杯算法模板常用套路及API等个人总结

版权声明:点个关注(^-^)V https://blog.csdn.net/weixin_41793113/article/details/88762953

写这篇博客的今天是19年的省赛考前的最后一天了,想写一些小白萌新们受益的东西

从最常考的全排列开始吧~

全排列模板1,最常用的写法

public class 全排列_模板1 {

	public static void main(String[] args) {
		dfs(0);
		System.out.println(ans);//9的全排有362880种
	}
	
	static int[] a = new int[] {1,2,3,4,5,6,7,8,9};
	
	static int n=9,ans=0;
	
	static void dfs(int m) {
		if(m>=n) {
			System.out.println("一些核心的操作 比如ans:"+ans);
			ans++;
			for(int i=0;i<n;i++)
				System.out.print(a[i]+" ");
			System.out.println();
			
			return;
		}
		
		for(int i=m;i<n;i++) {
			swap(i,m);
			dfs(m+1);
			swap(i,m);//回溯
		}
	
	
	}
	
	static void swap(int i,int j) {
		int t = a[i];
		a[i] = a[j];
		a[j] = t;
	}

}

全排列模板2,使用标记数组的写法

public class 全排列_模板2 {

	public static void main(String[] args) {
		vis = new boolean[n];
		b = new int[n];
		dfs(0);
		System.out.println(ans);//9的全排有362880种
	}
	
	static int[] a = new int[] {1,2,3,4,5,6,7,8,9};
	static int[] b;
	static boolean[] vis;
	static int n=9,ans=0;
	
	static void dfs(int m) {
		if(m>=n) {
			System.out.println("一些核心的操作 比如ans:"+ans);
			ans++;
			for(int i=0;i<n;i++)
				System.out.print(b[i]+" ");
			System.out.println();
			
			return;
		}
		
		for(int i=0;i<n;i++) 
			if(!vis[i]) {
				vis[i] = true;
				b[m] = a[i];
				dfs(m+1);
				b[m] = 0;//其实这个也可以不用回溯,它会被覆盖
				vis[i] = false;//回溯
			}
	
	}

}

下面是需要排重的全排_模板

在上面模板上使用了哈希表查重,把一些数组并接成字符串

import java.util.HashSet;

public class 全排列_模板3 {

	public static void main(String[] args) {
		dfs(0);
		System.out.println(ans);//9的全排有362880种
		System.out.println(set.size());//1680
	}
	
	static int[] a = new int[] {1,1,1,2,2,2,3,3,3};
	
	static int n=9,ans=0;
	static HashSet<String> set = new HashSet<>();
	
	static void dfs(int m) {
		if(m>=n) {
			System.out.println("一些核心的操作 比如ans:"+ans);
			ans++;
			String s="";
			for(int i=0;i<n;i++) {
				s+=a[i];
				System.out.print(a[i]+" ");
			}
			System.out.println();
			set.add(s);
			return;
		}
		
		for(int i=m;i<n;i++) {
			swap(i,m);
			dfs(m+1);
			swap(i,m);//回溯
		}
	
	}
	
	static void swap(int i,int j) {
		int t = a[i];
		a[i] = a[j];
		a[j] = t;
	}

}

使用哈希表查重后是无序的,那么遇到需要打印字典序的有重复元素的全排呢

leetcode 46. 全排列

leetcode 47. 全排列 II

子集的写法也和全排很相似

leetcode 78. 子集(Subsets) beat 100%

leetcode 90. 子集 II(Subsets II) beat 98.57%

判断闰年

	static boolean is(int x) {
		return x%400==0 || (x%4==0 && x%100!=0);
	}

筛素数O({\color{DarkBlue} n^{\tfrac{3}{2}}})

	static boolean is(int n) {
		if(n==1)
			return false;
		for(int i=2;i*i<=Math.sqrt(n);i++)
			if(n%i==0)
				return false;
		
		return true;
	}

倍筛法_素数O(nlogn)

public class 倍筛模板 {

	public static void main(String[] args) {
		boolean[] is = new boolean[1000005];
		is[1] = true;//true表示不是素数
		for(int i=2;i<1000005;i++)
			if(!is[2])
				for(int j=2*i;j<1000005;j+=i)
					is[j] = true;
		System.out.println(is[2004]);
	}

}

01背包

public class _01背包 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int m = in.nextInt();//大小
		int n = in.nextInt();//物品数
		int[] dp = new int[m+5];//开背包质量的大小
		for(int i=1;i<=n;i++) {
			int v = in.nextInt();//物品体积
			int w = in.nextInt();//物品价值
			for(int j=m;j>=v;j--)
				dp[j] = Math.max(dp[j], dp[j-v]+w);
		}
		System.out.println(dp[m]);
	}

}

完全背包

import java.util.Scanner;

public class _完全背包 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int m = in.nextInt();//大小
		int n = in.nextInt();//物品数
		int[] dp = new int[m+5];//开背包质量的大小
		for(int i=1;i<=n;i++) {
			int v = in.nextInt();//物品体积
			int w = in.nextInt();//物品价值
			for(int j=v;j<=m;j++)
				dp[j] = Math.max(dp[j], dp[j-v]+w);
		}
		System.out.println(dp[m]);
	}

}

最小公倍数gcd

	static int gcd(int a,int b) {
		return b==0?a:gcd(b,a%b);
	}

最大公约数lcm

	static int lcm(int a,int b) {
		return a*b/gcd(a,b);
	}

多个数共同的gcd和lcm模板

	static int gcd(int[] a) {
		int n = a.length;
		int g = a[0];
		for(int i=1;i<n;i++)
			g = gcd(g,a[i]);
		
		return g;
	}
	
	static int lcm(int[] a) {
		int n = a.length;
		int l = a[0];
		for(int i=1;i<n;i++)
			l = lcm(l,a[i]);
		
		return l;
	}

二分答案_模板

蓝桥杯 2017年第八届真题 分巧克力 经典的二分答案 输入挂

	static void f(int[] a) {
		int n = a.length;
		int l=0,r=n-1,ans=0;//一般上界需要自己构造
		while(l<=r) {
			int mid = l + (r-l)/2;
			if(ok(a[mid])) {
				r = mid-1;
				ans = mid;
			}else
				l = mid+1;
		}
		System.out.println(ans);
	}
	
	static boolean ok(int x) {
		return false;//按照题意写
	}

二分lower_bound的实现(找到第一个大于等于给定值key的那个数)如[1,2,2,3]查找2,会返回第一个2的下标

    public static int lowerBound(int []nums,int l,int r,int target){
        while(l<=r){//r=n-1
            int m = (l+r)/2;
            if(nums[m]>=target) r= m-1;
            else    l = m +1;
        }
        return l;
    }

upper_bound的实现(要求在按照非递减顺序排好序的数组中找到第一个大于给定值key的那个数)(不常用)

    public static int upperBound(int []nums ,int l,int r, int target){
        while(l<r){//其中 r = nums.length
            int m = (l+r)/2;
            if(nums[m]<=target) l = m+1;
            else    r = m;
        }
        return l;
    }

各种排序实现

  • 冒泡排序(学会手写)
  • 选择排序(没什么应用)
  • 插入排序(对近乎有序的数组复杂度提升到O(n))
  • 计数排序(给定区间排序)
  • 归并排序(求逆序数)
  • 快速排序(找第K大数)
  • 堆排序(优先队列API)
  • 希尔排序(插入排序的升级版)

大数类BigInteger和BigDecimal及方法API

考场上查API

进制问题,如有价值1,2,4,8等价值的硬币,如何用最小的硬币数凑出100元

	static int f(int n,int k) {//调用API转成k进制,缺点题目有上界为8
		int ans=0;
		String s = Integer.toString(n, k);
		System.out.println(s);
		for(int i=0;i<s.length();i++)
			ans+=s.charAt(i)-'0';
		
		return ans;
	}

头条面试题:找钱问题,共1024,64,16,4,1几种面值 

    static void solve(){
        Scanner cin = new Scanner(System.in);
        int N = 1024-cin.nextInt(), ans = 0;
        for(int i=0; i<4; i++){
            ans += N/arr[i];
            N %= arr[i];
        }
        System.out.println(ans);
    }
!

堆的应用,给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效

leetcode 20. 有效的括号(Valid Parentheses)

    public boolean isValid(String s) {
    	if(s==null||s.equals(""))
    		return true;
 
        char[] ch = s.toCharArray();
        Stack<Character> stack = new Stack<>();
        
        for(int i=0;i<ch.length;i++)
        {
        	if(ch[i]=='(' || ch[i]=='[' || ch[i]=='{')
        		stack.push(ch[i]);
        	else if(ch[i]==')' || ch[i]==']' || ch[i]=='}')
        	{
        		if(!stack.isEmpty())
        		{
	        		char p = stack.pop();
	        		if(p=='(' && ch[i]==')')
	        			continue;
	        		if(p=='[' && ch[i]==']')
	        			continue;
	        		if(p=='{' && ch[i]=='}')
	        			continue;
        		}
        		return false;
        	}
        }
        
        return stack.empty();
    }

快速幂及矩阵快速幂模板

矩阵幂_快速幂_矩阵乘法_模板

	static long mpow(long a,long n) {//快速幂,mod一般题目给1e9+7
		if(n==0 || a==1)
			return 1;
		long ans=1;
		while(n!=0) {
			if(n%2==1)
				ans = a*ans%mod;
			a=a*a%mod;
			n>>=1;
		}
		
		return ans;
	}

 矩阵乘法模板

//这里是矩阵的乘法模板,默认方阵
	static int[][] mul(int[][] a,int[][] b){
		int n = a.length;
		int[][] ans = new int[n][n];
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				for(int k=0;k<n;k++)
					ans[i][j] =(ans[i][j] + a[i][k]*b[k][j])%MOD;//ans[i][j] += a[i][k]*a[k][j];
		return ans;
	}

 矩阵快速幂模板


	//矩阵快速幂_模板
	static int[][] mpow(int[][] a,int n){
		int N = a.length;
		int[][] ans = new int[N][N];
		for(int i=0;i<N;i++)
			ans[i][i] = 1;//初始化为单位矩阵W
		while(n>0) {//写 n!=0也行,会快些么,反正位运算是会快的.这个不清楚
			if((n&1)==1) 
				ans = mul(ans,a);
			a = mul(a,a);
			n>>=1;
		}
		return ans;
	}

阶乘逆元求组合数C(n,m)模板_O(nlogn)

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		f = new long[n+5];
		inv = new long[n+5];
		f[0]=1;
		for(int i=1;i<n+5;i++) {
			f[i]=f[i-1]*i%mod;
			inv[i] = mpow(f[i],mod-2);
		}
		
		
	}
	
	static int n;
	static long mod = 1000000009;
	static long[] f;
	static long[] inv;
	
	static long C(int n,int m) {
		return f[n]*inv[m]%mod*inv[n-m]%mod;
	}
	
	static long mpow(long a,long n) {//快速幂
		if(n==0 || a==1)
			return 1;
		long ans=1;
		while(n!=0) {
			if(n%2==1)
				ans = a*ans%mod;
			a=a*a%mod;
			n>>=1;
		}
		
		return ans;
	}

欧拉函数模板        定义:小于n的正整数中与n互质的数的数目(φ(1)=1)

	static int Euler(int n) {//O(n) 有时候需要long
		int ans=n;
		
		for(int i=2;i<=n;i++) 
			if(n%i==0) {
				ans=ans/i*(i-1);
				while(n%i==0)
					n/=i;
			}
		
		return ans;
	}
	static int Euler(int n) {//O(sqrt(n))
		int ans=n;

		for(int i=2;i*i<=n;i++) 
			if(n%i==0) {
				ans=ans/i*(i-1);////n*(1-(1/p))转化为n/p*(p-1)
				while(n%i==0)
					n/=i;
			}
		if(n>1)//优化 O(sqrt(n)) 不过要在出口 if(n>1)ans/n*(n-1) O(n)不用
			ans=ans/n*(n-1);
		
		return ans;
	}

前缀和模板

import java.util.Scanner;

public class 前缀和模板 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] sum = new int[n+1];
		for(int i=1;i<=n;i++)
			sum[i] = sum[i-1] + in.nextInt();//前i个数的和

	}

}

线段树模板

并查集模板

	static int n,m,cnt=0;
	static int[] f = new int[10005];//初始化一般是f[i]=i
	
	static int find(int x) {
		if(f[x]==x)
			return x;
		return f[x] = find(f[x]);
	}
	
	static void union(int x,int y) {
		int a = find(x);
		int b = find(y);
		if(a!=b) {
			f[a] = b;
			cnt++;
		}
	}

dfs求联通块模板

	static int n,m;
	static int[][] vis;
	static char[][] ch;

	static int[] dx = new int[] {1,1,1,0,0,-1,-1,-1};
	static int[] dy = new int[] {0,-1,1,1,-1,1,0,-1};
	
	static void dfs(int t,int x,int y) {// hdu1241 油田问题 八联通
		vis[x][y] = t;
		
		for(int i=0;i<8;i++) 
			if(x+dx[i]>=0 && x+dx[i]<n && y+dy[i]>=0 && y+dy[i]<m && ch[x+dx[i]][y+dy[i]]=='@' && vis[x+dx[i]][y+dy[i]]==0)
				dfs(t,x+dx[i],y+dy[i]);
		
	}
			int t=0;
			for(int i=0;i<n;i++)
				for(int j=0;j<m;j++)
					if(ch[i][j]=='@' && vis[i][j]==0)
						dfs(++t,i,j);
			System.out.println(t);

最小生成树模板

	static int n,m,cnt=0,ans=0;
	static int[] f;
	
	static int find(int x) {
		if(f[x]==x)
			return x;
		return f[x] = find(f[x]);
	}
	
	static int union(int x,int y) {
		int a = find(x);
		int b = find(y);
		if(a!=b) {
			f[a] = b;
			return 1;
		}
		return 0;
	}
	
	
	static class Edge implements Comparable<Edge>{
		int a,b,c;
		public Edge(int a,int b,int c) {
			this.a = a;
			this.b = b;
			this.c = c;
		}
		@Override
		public int compareTo(Edge o) {
			return this.c - o.c;
		}
	}
	public static void main(String[] args) {
		InputReader in = new InputReader(System.in);  //用它来代替Scanner。
		while(true) {
			n = in.nextInt();
			if(n==0)
				break;
			m = n*(n-1)/2;
			cnt=0;
			ans=0;
			f = new int[n+5];
			for(int i=1;i<=n;i++)
				f[i] = i;
			
			PriorityQueue<Edge> pq = new PriorityQueue<>();
			
			for(int i=1;i<=m;i++) {
				int a = in.nextInt();
				int b = in.nextInt();
				int c = in.nextInt();
				int d = in.nextInt();
				if(d==1)
					cnt+=union(a,b);
				else
					pq.add(new Edge(a, b, c));
			}
			
			while(!pq.isEmpty()) {
				Edge u = pq.poll();
				if(union(u.a, u.b)==1) {
					cnt++;
					ans+=u.c;
					if(cnt==n-1)
						break;
				}
			}
			
			System.out.println(ans);
		}
		
		
	}

输入挂模板

	//解决javaIO读取过慢的方法,利用该类读取输入数据,不要用Scanner!!!
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

	}

拓扑排序模板

蓝桥杯 卡勒沃夫之弱水路三千(提高型) 拓扑排序+Map

		static ArrayList<Integer> list = new ArrayList<>();
	    static ArrayList<Integer>[] edge = new ArrayList[105];	
        
		while(m-->0) {//建图 邻接表 并且用w[i]记录入度
			String s1 = in.next();
			String s2 = in.next();
			if(!map.containsKey(s1))
				map.put(s1,n++);
			if(!map.containsKey(s2))
				map.put(s2,n++);
			w[map.get(s2)]++;
			edge[map.get(s1)].add(map.get(s2));
		}

    	for(int i:map.values())//把边为0的放进队列
				if(w[i]==0)
					q.add(i);
			while(!q.isEmpty()) {
				int u = q.poll();
				list.add(u);
				for(int v:edge[u]) {
					w[v]--;
					if(w[v]==0)
						q.add(v);
				}
			}

dijkstra模板O(n^2)

dijkstra邻接表+优先队列模板O(nlogn)

猜你喜欢

转载自blog.csdn.net/weixin_41793113/article/details/88762953
今日推荐