算法模板七月

数学类模板

求组合数模板

求组合数 蓝桥杯集合的分割;

static int mod = 1000000000 + 7;
static int N = 1010;
//求
 static  long [][] arr=new long[N][N]; //需要开一个long
 static  {
        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++) { //这边也是根号n
            if (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;//将最大的赋值给res
                maxLeb = 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;
    }

    @Override
    public 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求无权图的单元最短路径。

你可能感兴趣的:(算法,开发语言,java)