Summary of commonly used algorithm code templates

The following content only provides convenient and easy-to-use templates for the corresponding algorithms, or makes a certain function into a function and calls it directly by passing parameters. No detailed algorithm proof is provided. Most algorithms are written in Java and can be converted into other languages. The content that is too long will be summarized in a separate blog, and the corresponding practice questions will be given in the blog. Continuously updating...

Table of contents

quick sort

merge sort

heap sort

Prefix sum and difference (1D, 2D)

And lookup

integer dichotomy, floating point dichotomy

Remove duplicate elements in the array (double pointer)

Find the greatest common divisor

Find the lowest common multiple

Find prime numbers (Eulerian sieve)

High-precision addition (C++)

High-precision subtraction (C++)

High-precision multiplication (C++)

High-precision division (C++)

Dynamic programming knapsack problem

KMP algorithm of pattern matching algorithm

Prim algorithm for minimum spanning tree (undirected graph)

Kruskal algorithm for minimum spanning tree (undirected graph)

Dijkstra's algorithm for single source shortest path (undirected graph)

Bellman-ford algorithm for single source shortest path (directed graph)

Floyd algorithm for multi-source shortest path (directed graph)

warshall algorithm determines whether the graph is connected (adjacency matrix stores the graph)


quick sort

Quick sort java code template

merge sort

Merge sort java code template

heap sort

Heap sorting and simulated heap java code template

Prefix sum and difference (1D, 2D)

Prefix sum and difference code template

And lookup

And check the java code template

integer dichotomy, floating point dichotomy

Integer binary, floating point binary code template

Remove duplicate elements in the array (double pointer)

public static void main(String args[]) {
		int[] nums = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 7 };
		int j = 0;

		for (int i = 0; i < nums.length; i++) {//去除数组当中重复的元素
			if (i == 0 || nums[i] != nums[i - 1])
				nums[j++] = nums[i];
		}

		for (int i = 0; i < j; i++)
			System.out.print(nums[i] + " ");//输出:1 2 3 4 5 6 7 
	}

Find the greatest common divisor

Simple method

public static int gcd(int a, int b) {// 最大公约数朴素写法,传入两个数,返回最大公约数。
		while (b != 0) {
			int temp = a % b;
			a = b;
			b = temp;
		}
		if (a < 0)
			return -a;
		return a;
}

 Recursive writing

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

Find the lowest common multiple

public static int gbs(int n, int m) {//传入两个数,得到两个数的最小公倍数

    int temp = Math.max(n, m);//求得这两个数的较大值
    for (int i = temp; ; i++) {//从较大值开始遍历
        if (i % n == 0 && i % m == 0)
            return i;
    }

}

Find prime numbers (Eulerian sieve)

public static int[] Prime(int n) {// 欧拉筛求素数,传入参数n表示范围的最大值
		int[] prime = new int[100010];// 能够存放的素数个数
		boolean[] bool = new boolean[100010];
		int count = 0;// 记录素数个数
		for (int i = 2; i <= n; i++) {
			if (bool[i] == false) {
				prime[count++] = i;
				bool[i] = true;
			}
			for (int j = 0; j < count; j++) {
				if (i * prime[j] > n)
					break;
				bool[i * prime[j]] = true;
				if (i % prime[j] == 0)
					break;
			}
		}
		System.out.printf("0~%d范围内的素数个数为:%d\n", n, count);// 输出个数
		return prime;
	}

High-precision addition (C++)

Java and python do not need high precision. Java uses BigInteger, python is more convenient.

vector<int> add(string a, string b){//传入两个数的字符串形式,返回之和。 
	 	
		if (a.length() < b.length()) return add(b, a);

        int t = 0;
		vector<int> A, B, c;
	    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
	    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

	    
	    for (int i = 0; i < A.size(); i ++ ){
	        t += A[i];
	        if (i < B.size()) t += B[i];
	        C.push_back(t % 10);
	        t /= 10;
	    }

	    if (t) C.push_back(t);
	    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
	    return C;
	}

High-precision subtraction (C++)

High-precision subtraction involves the judgment of positive and negative signs, which is a little more complicated.

bool cmp(vector<int> &A, vector<int> &B)//正负号判断
{
    if (A.size() != B.size()) return A.size() > B.size();

    for (int i = A.size() - 1; i >= 0; i -- )
        if (A[i] != B[i])
            return A[i] > B[i];

    return true;
}

vector<int> sub(vector<int> &A, vector<int> &B)//传入数字,返回差。
{
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;
        else t = 0;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

int main()
{
    string a, b;
    vector<int> A, B;
    cin >> a >> b;//输入两个字符串形式的数组,返回其差
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

    vector<int> C;

    if (cmp(A, B)) C = sub(A, B);//根据正负号的不同选择不同的相减方式
    else C = sub(B, A), cout << '-';

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
    cout << endl;

    return 0;
}

High-precision multiplication (C++)

High-precision multiplication of two numbers generally results in only one number being very large.

vector<int> mul(string a, long b){//传入一个数的字符串形式和另一个数,返回其乘积。 
	
	vector<int> A, c;
    int t = 0;
    
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
	
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
	//for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
    return C;
}

High-precision division (C++)

vector<int> div(string a, int b, int &r)//传入 
{
	vector<int> A, c;
	r = 0;//记录余数 
	
	for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    
    for (int i = A.size() - 1; i >= 0; i -- )
    {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    printf("\n余数为:%d\n",r); 
    return C;
}

Dynamic programming knapsack problem

Summary of Dynamic Programming Knapsack Problem

KMP algorithm of pattern matching algorithm

Graphical KMP algorithm principle and code analysis

Prim algorithm for minimum spanning tree (undirected graph)

Prim algorithm java code template for minimum spanning tree

public static int prim(int n, int[][] map) {//从下标1开始记录图的数据,n个节点,返回最小生成树的边权之和

		int[] dist = new int[n + 10];// 含义:这个点到最小生成树那个集合的最短距离,点到集合的距离
		boolean[] st = new boolean[n + 10];// st数组表示这个点有没有被加入最小生成树集合,如果被加入了,st[i]=true
		Arrays.fill(dist, INF);// 初始化距离

		int result = 0;// 记录最小生成树所有边权之和

		for (int i = 0; i < n; i++) {
			int t = -1;// 第一个点时情况特别判断
			for (int j = 1; j <= n; j++) {// 找到集合外距离集合最近的点
				if (st[j] == false && (t == -1 || dist[t] > dist[j]))
					t = j;
			}
			if (i != 0 && dist[t] == INF)// 如果最小的节点长度都为INF,那么不用找了,不存在最小生成树
				return INF;
			if (i != 0)// 如果这个点不是第一个点,将这个点距离加入
				result += dist[t];

			st[t] = true;// 将t这个点加入集合当中
			for (int j = 1; j <= n; j++)// 用这个点来更新其他点到这个集合的最短距离
				dist[j] = Math.min(dist[j], map[t][j]);// 这个时候t这个点已经被加入集合当中了,所以其他点到集合的距离可以用t来更新,因为t也在集合当中。

		}
		return result;
	}

Kruskal algorithm for minimum spanning tree (undirected graph)

Minimum spanning tree Kruskal algorithm java code template

static int[] p;

	public static int Find(int x) {// 并查集路径压缩优化
		if (p[x] != x)
			p[x] = Find(p[x]);
		return p[x];
	}
// kruskal算法略显繁琐,需要用到并查集
	public static int kruskal(int n, int[][] way) {// n个点,way记录的是边的信息
		
		p=new int[n+10];
		
		Arrays.sort(way, new Comparator<int[]>() {// 重写比较器,以边的权值作为比较依据
			public int compare(int[] o1, int[] o2) {
				return o1[2] - o2[2];
			}
		});

		for (int i = 1; i <= n; i++)// 并查集初始化每一个点,都是以自己为根节点的集合
			p[i] = i;

		int result = 0, count = 0;
		for (int i = 0; i < way.length; i++) {
			int a = way[i][0];
			int b = way[i][1];
			int c = way[i][2];
			a = Find(a);// 查询a的根节点
			b = Find(b);// 查询b的根节点
			if (a != b) {// 如果a和b不在一个集合里面
				p[a] = b;// 将a的根节点的父节点指向b
				result += c;// 加上这条边的距离
				count++;// 合并的点数加1
			}
		}

		if (count < n - 1)// 如果连通的点少于了点的总个数,说明不能构成最小生成树
			return Integer.MIN_VALUE;
		return result;

	}

Dijkstra's algorithm for single source shortest path (undirected graph)

Single source shortest path Dijkstra algorithm java code template

public static int[] Dijkstra(int[][] map) {// 传入一个临界矩阵存放的图,从下标0开始为第一个点,返回所有点到第一个节点的最短距离数组。
		// 注意邻接矩阵存放的图初始化的数值是由你自己确认的!
		int n = map.length;
		int[] dist = new int[n];// 存放点到初始点的距离
		boolean[] st = new boolean[n];// 存放是否确定到初始点的距离最短
		Arrays.fill(dist, Integer.MAX_VALUE);// 初始化存放的所有节点到第一个节点的距离为无穷大

		dist[0] = 0;// 初始点到自己的距离为0

		for (int i = 0; i < n - 1; i++) {
			int temp = -1;
			for (int j = 0; j < n; j++) {// 如果矩阵从1开始存放节点信息,修改为for (int j = 1; j <= n; j++)

				if (st[j] == false && (temp == -1 || dist[temp] > dist[j]))// 第一次替换找到没有标记确定的第一个点,之后循环找距离初始点最近的没有标记确定的点
					temp = j;
			}

			// 如果矩阵从1开始存放节点信息,修改为for (int j = 1; j <= n; j++)
			for (int j = 0; j < n; j++) {// 通过上一步找到的点来更新这个点能够到达的其他点的距离
				// map[temp][j]表示temp到j这个点的距离,再加上dist[temp]就表示初始点以temp为中间点到j的距离
				dist[j] = Math.min(dist[j], dist[temp] + map[temp][j]);
			}
			st[temp] = true;// 更新完成之后,将该点标记为确定
		}
		return dist;// 返回结果
	}

Bellman-ford algorithm for single source shortest path (directed graph)

Single source shortest path Bellman-ford algorithm java code template

public static int[] Bellman_Ford(int n, int[][] way) {// n个点,way表示边的信息,way[i][j]=a表示从i到j距离为a,节点的下标从1开始记录,返回从第一个点到所有点最近的距离

		int[] dist = new int[510];// 存放到某点的距离
		int[] temp = new int[3];// 存放单条边
		Arrays.fill(dist, Integer.MAX_VALUE / 20);// 初始化
		dist[1] = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				temp = way[j];
				dist[temp[1]] = Math.min(dist[temp[1]], dist[temp[0]] + temp[2]);
			}
		}
		return dist;
	}

Floyd algorithm for multi-source shortest path (directed graph)

Multi-source shortest path floyd algorithm java code template

public static int[][] floyd(int n, int[][] map) {// 三重循环,n个点传入邻接矩阵存放的图map,返回多个点之间的最短路径数组
		// 刚开始传入的是邻接矩阵图,返回的是距离map[i][j]=a表示从i到j最短距离为a
		// 刚开始邻接矩阵的初始化自行处理。
		for (int k = 1; k <= n; k++) {
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++)
					map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
			}
		}
		return map;
	}

warshall algorithm determines whether the graph is connected (adjacency matrix stores the graph)

public static boolean Warshall(int[][] tmp, int n) {// 传入这个图的邻接矩阵和节点个数。判断图是否连通,连通返回true

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (tmp[i][j] == 1) {
					for (int k = 0; k < n; k++) {
						if (tmp[k][i] == 1)
							tmp[k][j] = tmp[j][k] = 1;
					}
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				if (tmp[i][j] != 1)
					return false;
		return true;
	}

Guess you like

Origin blog.csdn.net/weixin_41746479/article/details/121291233