数学类模板
求组合数模板
求组合数 蓝桥杯集合的分割;
static int mod = 1000000000 + 7;
static int N = 1010;
//求static long [][] arr=new long[N][N]; //需要开一个longstatic {for (int i = 0; i < N; i++) {for (int j = 0; j <= i; j++) {if (j== 0) {arr[i][j] = 1;} else {arr[i][j] = (arr[i-1][j]+arr[i-1][j-1])%mod;}}}}
质数模板
质数的一些性质
任何一个大于1的数都可以表示为一个质数的n倍;
埃筛法求质数
public class 线性筛 {public static void main(String[] args) {Scanner scanner =new Scanner(System.in);int n=scanner.nextInt();boolean [] isPrime=aishishai(n);for (int i = 0; i <=n; i++) {if (isPrime[i]){System.out.print(i+" ");}}}public static boolean[] aishishai(int n){boolean [] isPrime=new boolean[n+1];//创建一个n+1长度的数组Arrays.fill(isPrime,true);isPrime[0]=false;isPrime[1]=false;for (int i = 2; i*i<=n; i++) { //这边也是根号nif (isPrime[i]){for (int j = i*i; j <=n ; j+=i) { //2*i 3*i 4*i//当 i = 2 时,isPrime[2] 为 true,将从 2*2 = 4 开始的所有偶数标记为 false:// [false, false, true, true, false, true, false, true, false, true,// false, true, false, true, false, true, false, true, false, true,// false, true, false, true, false, true, false, true, false, true, false, true]isPrime[j]=false;}}}return isPrime;}
}
时间复杂度 O(n log(log n))。
阶乘模板
21的阶乘就已经超过了long类型;
基础模板
二分查找
二分查找的基础模板
在一共有序的数组中寻找一个数字,用二分查找的方式
采用的是左闭右闭得模式,while里面是小于等于
int binarySearch(int[] nums, int target) {int left = 0; int right = nums.length - 1; //左闭右闭while(left <= right) {int mid = left + (right - left) / 2;//防止结果溢出if(nums[mid] == target)return mid; else if (nums[mid] < target)left = mid + 1; // 注意else if (nums[mid] > target)right = mid - 1; // 注意}return -1;
}
二分查找还具有其他得作用,可以查找左边界和右边界
寻找左边界得二分搜索左闭右闭的写法
int left_bound(int[] nums, int target) {if (nums.length == 0) return -1;int left = 0, right = nums.length;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {// 当找到 target 时,收缩右侧边界right = mid;} else if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid;}}return left;
}
二分查找应用实际的题目,寻找左边界
Leetcode 1011在D天内送达包裹的能力;
哈希表
一般用来判断元素在集合中是否出现过,常用的哈希的方法有 数组 set集合 map集合
leetcode 1; 用map集合来存储出现的元素,如果target-nums[i]在map中出现了,那么就找出来了nums[i]+nums[j]=target;
数组做映射 lt,有效字母的异位词,判断一个字母是否在另一个字母里面全部都出现过,
首先遍历第一个字母,用的是records[s.charAt(i)-‘a’]++,索引是对应的字母,索引对应的值是对应出现的次数。然后再遍历另一个字符串将出现的–,最后遍历这个数组;
用set集合来做映射,求两个数组之间的交集,一共字母可能出现了多次,如何解决呢,应该用set,遍历第一个字符串,添加到set1中,遍历第二个,如果set1中有那么就添加到set2中去,再将set2转为数组即可;
双指针模板
例题删除数组中重复的元素,需要原地删除,不能创建一个新的数组
slow=0,fast=0;
fast<nums.length
快指针进行移动,如果slow指针和fast指针对应的值不相等,需要往前移动slow指针,并且fast的值需要赋值给slow;列题 移除数组中的元素,需要原地进行移除,想要时间复杂度变得很小如何去做呢?left=0,right=nums.length;
left<right; 如果左边的值等于了val,将右边的值赋值给左边,同时right--;左边的值不等于右边就是left不断地++;
处理字符串有一个叫做中心扩散法则,
class Solution {public String longestPalindrome(String s) {//最长回文的字串 中心扩散法则int len = s.length();if (len < 2) return s;int[] res = new int[2];int maxLeb = 0;for (int i = 0; i < s.length(); i++) {int odd[] = centerSpread(s, i, i);int[] even = centerSpread(s, i, i + 1);int[] max = odd[1] > even[1] ? odd : even;if (max[1] > maxLeb) {res = max;//将最大的赋值给resmaxLeb = max[1];}}//res[0]是左边界 res[1]是对应的长度;return s.substring(res[0], res[0] + res[1]);}public int[] centerSpread(String s, int left, int right) {int len = s.length();while (left >= 0 && right < len) {if (s.charAt(left) == s.charAt(right)) {left--;right++} else {break;}}//索引1是对应的坐标,索引二是对应的长度;return new int[]{left + 1, right - left - 1}}
}
数据结构模板
优先队列
什么时候应该使用优先队列?
求前k个元素.... 不断利用高位元素 求中位数
优先队列的模板题 leetcode 973
class Solution {public int[][] kClosest(int[][] points, int k) {PriorityQueue<long[]> queue =new PriorityQueue<>((a,b)->Long.compare(b[0],a[0]));//比较的就是距离远点的平方; //比较规则的时候,需要使用long的包装类for (int i = 0; i < points.length; i++) {int []cur=points[i]; //当前数组queue.add(new long[]{1L*cur[0]*cur[0]+cur[1]*cur[1],1l*i});//把对应的距离 和索引都加到数组中去,数组在加到队列中去if (queue.size()>k){//寻找k个元素,如果大于了k,就需要讲小的进行返回,规则就是小的在·前queue.poll();}}int [][]ans=new int[k][];int p=0;while (!queue.isEmpty()) {ans[p++] = points[(int)queue.poll()[1]];}return ans;}
}//优先队列就是可以根据自己的需要对元素进行排序,如果排序的规则比较复杂可以定义一个类来实现规则
public class Seg implements Comparable<Seg>{int len,l,r;public Seg(int len, int l, int r) {this.len = len;this.l = l;this.r = r;}@Overridepublic int compareTo(Seg o) {if (len==o.len){return l-o.l; //返回一共数,升序排序}else {//长度不等,就看谁的长度大return o.len-len;//进行降序排序}}
}
图论模板
并查集模板,并查集有三个步骤 :1初始化,每一个节点的父节点都是自己
2找到根节点,需要进行路径压缩,将所有子节点都指向一个父节点
3联合,找到两个节点的父节点,将一个节点的父节点指向另一个节点
题目(244条消息) 【蓝桥杯】 历届试题 合根植物(并查集)_csdn_theSerein的博客-CSDN博客
public class BING {static int fa[];public static void main(String[] args) {int n ,m,x,y;Scanner scanner =new Scanner(System.in);n=scanner.nextInt();m=scanner.nextInt();fa=new int[n+1];init(n);for (int i = 1; i <=m; i++) {//自身指向自己的节点x=scanner.nextInt();y=scanner.nextInt();union(x,y);}int q=scanner.nextInt();for (int i = 0; i < q; i++) {if (find(scanner.nextInt())!=find(scanner.nextInt())){System.out.println("NO");}else {System.out.println("YES");}}}//路径压缩的代码static void init(int n){for (int i = 1; i <=n; i++) {fa[i]=i;}}static int find(int i){if (fa[i]==i){ //如果父节点是自身的话,直接返回就行了return i;}else{fa[i]=find(fa[i]);//将i的父节点加入进来,进行递归return fa[i];//是i的父节点}}//通过这一段代码,将所有的节点都指向了一个父节点static void union(int i,int j){int i_fa=find(i); //找到对应的节点int j_fa=find(j);//fa[i_fa]=j_fa;//将节点进行合并操作}
}
Dijkstra算法模板
bfs求无权图的单元最短路径。