MindMap Gallery Design and Analysis of Algorithms
The map introduces several basic algorithms, including: divide and conquer, dynamic programming, greedy, backtracking, and branch and bound. Suitable for beginners to have a preliminary understanding of algorithms. At the same time, it is equipped with a large number of cases and pictures to help understand the content and ideas of the algorithm.
Edited at 2021-07-23 12:47:52One Hundred Years of Solitude is the masterpiece of Gabriel Garcia Marquez. Reading this book begins with making sense of the characters' relationships, which are centered on the Buendía family and tells the story of the family's prosperity and decline, internal relationships and political struggles, self-mixing and rebirth over the course of a hundred years.
One Hundred Years of Solitude is the masterpiece of Gabriel Garcia Marquez. Reading this book begins with making sense of the characters' relationships, which are centered on the Buendía family and tells the story of the family's prosperity and decline, internal relationships and political struggles, self-mixing and rebirth over the course of a hundred years.
Project management is the process of applying specialized knowledge, skills, tools, and methods to project activities so that the project can achieve or exceed the set needs and expectations within the constraints of limited resources. This diagram provides a comprehensive overview of the 8 components of the project management process and can be used as a generic template for direct application.
One Hundred Years of Solitude is the masterpiece of Gabriel Garcia Marquez. Reading this book begins with making sense of the characters' relationships, which are centered on the Buendía family and tells the story of the family's prosperity and decline, internal relationships and political struggles, self-mixing and rebirth over the course of a hundred years.
One Hundred Years of Solitude is the masterpiece of Gabriel Garcia Marquez. Reading this book begins with making sense of the characters' relationships, which are centered on the Buendía family and tells the story of the family's prosperity and decline, internal relationships and political struggles, self-mixing and rebirth over the course of a hundred years.
Project management is the process of applying specialized knowledge, skills, tools, and methods to project activities so that the project can achieve or exceed the set needs and expectations within the constraints of limited resources. This diagram provides a comprehensive overview of the 8 components of the project management process and can be used as a generic template for direct application.
No relevant template
Chapter 1 Introduction to Algorithms
1.1 Algorithms and Programs
1. Enter
There are zero or more external quantities as inputs to the algorithm
2. Output
The algorithm produces at least one quantity as output
3. Certainty
Each instruction that makes up the algorithm is clear and unambiguous
4. Limitation
Each instruction in the algorithm has a limited number of executions, and the time to execute each instruction is also limited.
1.2 Abstract mechanism for expressing algorithms
1. Benefits of high-level programming languages
· Closer to algorithmic language, easy to learn and master
· Provides a structured programming environment and tools, making the program more readable, maintainable and reliable.
· Does not depend on machine language, has little to do with hardware, has good portability and high reuse rate
· High degree of automation and short development cycle
2. Benefits of abstract data types
· Separate the top-level design of the algorithm from the underlying implementation, without having to consider the underlying implementation
· Algorithm design is separated from data structure design, and algorithm efficiency is optimized.
1.3 Algorithm steps
1. Problem statement
· Is the meaning of each sentence or word in the question clear?
· What information has been given
· What results do you want to find?
· Whether the information given has redundant parts
· Is there any hidden information?
· Whether certain assumptions have been made
...
2. Model preparation
· What is the mathematical model that best fits this problem?
· Are there any other problems similar to this that have been solved?
...
3. Algorithm design (*)
4. Proof of algorithm correctness
· Provide proofs for each step, especially the conditions and lemmas that exist before and after the execution of this step
· Provide evidence that the algorithm will terminate
5. Algorithm implementation (*)
6. Algorithm complexity analysis
· The memory space and running time required by the algorithm need to be estimated or bounded
· Ability to use quantitative criteria to compare the efficiency of different algorithms for the same problem
7. Experimental testing
(1) 4 aspects of experimental testing
· Selection question: what to test, purpose of testing
· Determine metrics
· Generate test data
· Programming and running
(2) Data analysis
· Ratio test
· Power test
8. Documentation
Content includes: 1. Problem description and analysis 2. Modeling and Solving 3. Algorithm design and correctness proof process 4. Algorithm complexity analysis 5. Test result records and analysis reports 6. Input/output requirements and format description, etc.
1.4 Algorithm complexity analysis
1. Representation of algorithm time complexity
Let T(N, I) represent the time complexity of algorithm A on an abstract computer. in: · N: the size of the problem to be solved DN: The set of all possible inputs of size N · P(DN): Probability distribution of DN · I: input to the algorithm
2. Measurement of time complexity
· Worst case scenario:
· Best case scenario:
Not as a metric
· Average situation:
3. Asymptotic complexity
If there is a positive constant C and a natural number N such that f(n) <= C·g(n) when n >= N, then the function f(n) is said to be upper bounded when n is sufficiently large, and g( n) is an upper bound of it, denoted as f(n) = O(g(n)) · Compact upper bound: f(n) = C·g(n) · Non-compact upper bound: f(n) < C·g(n) (non-compact upper bound is represented by o)
If there is a positive constant C and a natural number N such that f(n) <= C·g(n) when n >= N, then the function f(n) is said to be bounded when n is sufficiently large, and g(n ) is a lower bound of it, denoted as f(n) = W(g(n)) · Compact lower bound: f(n) = C·g(n) · Inexact lower bound: f(n) > C·g(n), (inexact lower bound is represented by ω)
We note f(n) = Q(g(n)) if and only if f(n) = O(g(n)) and f(n) = W(g(n)), then f(n ) is of the same order as g(n)
For any given ϵ > 0, there exists a positive integer N such that f(n)/g(n) < ϵ when n >= N, then it is called the order ratio of the function f(n) when n is sufficiently large g(n) is low, which is a non-compact upper bound, denoted as f(n) = o(g(n))
For any given w > 0, there exists a positive integer N such that when n >= N, f(n)/g(n) > w, then it is called the order ratio of the function f(n) when n is sufficiently large. The height of g(n) is a non-compact lower bound, denoted as f(n) = w(g(n))
4. Understand
(1) Question
How to express that the upper bound of f(n) is g(n)? According to the concept of sets in mathematics, should be expressed as: f(n) ∈ O(g(n))
(2) answer
The algorithm is expressed as: f(n) = O(g(n)) Benefits: It intuitively expresses the meaning that the upper bound of complexity f(n) is g(n). · Cannot be written as O(g(n)) = f(n) · Do not use the writing method O(f) O(g) = f(N) G(N) · O(g(n)) can also represent any function with g(n) as the upper bound · O(1) represents a constant
Chapter 2 Recursion and Divide and Conquer Strategy
2.1 Recursion
1. Recursive definition
An algorithm that calls itself directly or indirectly is called a recursive algorithm. A function defined in terms of itself is called a recursive function.
2. Common recursive algorithms
(1) Factorial n!
(2) Fibonacci sequence
(3) Ackerman function
3. Application examples
(1) Arrangement problem
Problem statement
Design a recursive algorithm to generate all permutations of elements in R = {r1, r2, ... , rn}
Notation convention
· Ri = R - ri
· The complete arrangement of elements in set X is denoted by perm(X)
· (ri)perm(X) represents the permutation obtained by adding the prefix ri before each permutation of the full permutation perm(X)
Recursion formula
(2) Integer division problem
Problem statement
Represent a positive integer n as the sum of a series of positive integers:
Analysis of ideas
· According to the definition of partition, the maximum addend of partition is n1
· Record the number of divisions of the maximum addend n1<=m as q(n,m)
Recursion formula
(3) Hanoi Tower Problem
Problem statement
Suppose a, b, and c are three tower bases. There are n disks on a, stacked from small to large from top to bottom, numbered 1, 2, ⋯, n. Now we want to move the disks on a to b and still stack them in the same order. The following rules should be followed when moving the disc: · Rule 1: Only one disk can be moved at a time; · Rule 2: The big disc is not allowed to be pressed on the small disc at any time; · Rule 3: On the premise that moving rules 1 and 2 are met, the disc can be moved to any tower base in a, b, or c.
recursive algorithm
public static void hanoi(int n, int a, int b, int c) { if (n > 0) { hanoi(n-1, a, c, b); move(a,b); hanoi(n-1, c, b, a); } }
2.2 The basic idea of divide and conquer
1. Basic idea
(1) Divide large problems that are difficult to solve directly into several sub-problems
(2) Solve each sub-problem separately
(3) Then merge the solutions to the sub-problems to get the solution to the big problem
2. General algorithm design
1. Common pattern code
divide-and-conquer(P) { if (|P| <= n0) adhoc(P); divide P into smaller subinstances P1, P2, ... , Pk; for (i = 1, i <= k; i ) yi = divide-and-conquer(Pi); return merge(y1, ... , yk); }
2. Description
|P|
The size of problem P
n0
A threshold value, indicating that when the scale of problem P does not exceed n0, it is easy to solve and does not need to be decomposed.
adhoc(P)
Basic sub-algorithms in divide and conquer
merge(y1, ... yk)
Merge sub-algorithm in divide and conquer method
3. Related analysis
(1) Premise
For convenience, let the number of sub-problems at each level of decomposition be k, the decomposition threshold n0=1, and it takes 1 unit of time for adhor to solve a problem of scale 1. Let f(n) be the time required to decompose the original problem into k sub-problems and use merge to merge the solutions of the k sub-problems into the solution of the original problem. T(n) is the divide-and-conquer method divide-and-conquer(P ) is the computational time required to solve a problem of size |P|=n.
(2) Recursion relationship
(3) Solve
(4) Supplement
If f(n) = c·ni, the solution of the equation is:
4. Algorithm description
divide-and-conquer(P) { if ( | P | <= n0) adhoc(P); //Solve small-scale problems //!1: DIVIDE: Decompose the problem divide P into smaller subinstances P1,P2,...,Pk; //!2: CONQUER: Solve each sub-problem recursively for (i=1,i<=k,i) yi = divide-and-conquer(Pi); //!3: MERGE: Merge the solutions of each sub-problem into the solution of the original problem return merge(y1,...,yk); }
2.3 Binary search technology
1 Introduction
The binary search algorithm is a typical example of using the divide-and-conquer strategy. This method makes good use of the condition that n elements have been sorted, reducing the time complexity from O(n) for sequential search to O(logn)
2. Algorithm description (java language)
· Non-recursive
public static int binarySearch(int[] a, int x, int n) { // Search for x in a[0] <= a[1] <= ... <= a[n-1] // When x is found, return its position in the array, otherwise return -1 int left = 0; int right = n - 1; while (left <= right) { int middle = (left right)/2; if (x == a[middle]) return middle; if (x > a[middle]) left = middle 1; else right = middle - 1; } return -1; // x not found }
· recursion
public static int binSearch(int srcArray[], int start, int end, int key) { int mid = (end - start) / 2 start; if (srcArray[mid] == key) { return mid; } if (start > end) { return -1; } else if (key > srcArray[mid]) { return binSearch(srcArray, mid 1, end, key); } else if (key < srcArray[mid]) { return binSearch(srcArray, start, mid - 1, key); } return -1; }
2.4 Multiplication of large integers
1. Introduction to the problem
Usually, when analyzing algorithm complexity, addition and multiplication operations are treated as basic operations. However, in some cases, we have to deal with very large integers, which cannot be represented directly in the computer, so we need to use software methods to implement the calculation of large integers. Assume that X and Y are both n-bit binary large integers, and now calculate their product. For simplicity, n is a power of 2.
2. Algorithm ideas
· Divide n-bit binary integers X and Y into 2 segments, each segment is n/2 bits long, as shown in the figure:
· From this, we can get:
· Write the product of X and Y in the following form:
· Therefore, each calculation only needs to do 3 multiplications of n/2-digit integers, 6 additions and subtractions, and 2 shifts.
3. Recursion formula
4. Solve
2.5 Strassen matrix multiplication
1. Introduction to the problem
In the process of calculating matrix multiplication, we remember two n-order matrices as A and B, and the product is C. Then calculating each element C[i][j] of C requires n multiplication operations and n - 1 addition operations. Therefore, the calculation time required to calculate n2 elements of C is O(n3), which obviously needs improvement. To simplify the problem, let us write n as a power of 2.
2. Algorithm ideas
· Divide each matrix in matrices A, B and C into 4 sub-matrices of equal size, as shown in the figure:
· In order to reduce the multiplication calculation, we first perform the following 7 calculations:
· Then, we express Cij as follows:
3. Recursive formula
4. Solve
2.6 Checkerboard coverage
1. Introduction to the problem
In a chessboard consisting of 2k·2k squares, there is exactly one square that is different from the other squares. This square is called a special square, and the chessboard is a special chessboard. We are required to use 4 different shapes of L-shaped dominoes to cover the non-special squares on the given special chessboard, and the coverage is not allowed to be repeated.
2. Algorithm ideas
· Divide the 2k·2k chessboard into four 2k-1·2k-1 sub-boards, so the special square must be located on one of the sub-boards, leaving three sub-boards without special squares:
· We use an L-shaped domino to cover the intersection of the three sub-boards, as shown in the picture:
· Repeat until it is reduced to a 1·1 chessboard
3. Recursion formula
4. Solve
5. Algorithm description
public void chessBoard(int tr, int tc, int dr, int dc, int size) //tr:row, tc:column { if (size == 1) return; int t = tile, // L-shaped tile number s = size/2; // Split the chessboard if (dr < tr s && dc < tc s) // if-else statement processes the upper left corner chessboard chessBoard(tr, tc, dr, dc, s); // The special square is on this chessboard else {//There are no special squares on this board board[tr s - 1][tc s - 1] = t; // Cover the lower right corner with L-shaped dominoes numbered t chessBoard(tr, tc, tr s-1, tc s-1, s); // Cover the remaining squares } if (dr < tr s && dc >= tc s) // if-else statement processes the upper right corner chessboard chessBoard(tr, tc s, dr, dc, s); // The special square is on this chessboard else {//There are no special squares on this board board[tr s - 1][tc s] = t; // Cover the lower left corner with L-shaped dominoes numbered t chessBoard(tr, tc s, tr s-1, tc s, s); // Cover the remaining squares } if (dr >= tr s && dc < tc s) // if-else statement processes the lower left corner chessboard chessBoard(tr s, tc, dr, dc, s); // The special square is on this chessboard else {//There are no special squares on this board board[tr s][tc s - 1] = t; // Cover the upper right corner with L-shaped dominoes of size t chessBoard(tr s, tc, tr s, tc s-1, s); // Cover the remaining squares } if (dr >= tr s && dc >= tc s) // if-else statement processes the lower right corner chessboard chessBoard(tr s, tc s, dr, dc, s); // The special square is on this chessboard else { // There are no special squares on this board board[tr s][tc s] = t; // Cover the upper left corner with L-shaped dominoes of size t chessBoard(tr s, tc s, tr s, tc s, s); // Cover the remaining squares } }
2.7 Merge sort
1. Algorithmic thinking
Divide the elements to be sorted into two sub-sets of roughly the same size, sort the sub-sets respectively, and finally merge the sorted sub-sets into the required set
2. Recursive formula
3. Solve
4. Example
5. Algorithm description
public static void mergeSort(Comparable a[], int left, int right) { if (left<right) {//At least 2 elements int i=(left right)/2; //Get the midpoint mergeSort(a, left, i); mergeSort(a, i 1, right); merge(a, b, left, i, right); //Merge into array b copy(a, b, left, right); //Copy back to array a } }
2.8 Quick sort
1. Algorithm idea
(1) Decomposition
Using a[p] as the base element, divide a[p:r] into 3 segments: a[p:q-1], a[q] and a[q 1:r], such that a[p:q-1 Any element in ] is less than or equal to a[q], any element in a[q 1:r] is greater than or equal to a[q]
(2) Recursive solution
Recursive call to sort a[p:q-1] and a[q 1:r]
(3) Merge
No calculation is required, the order has been sorted after the recursion
2. Recursive formula
(1) Worst case scenario
(2) Best case scenario
3. Solve
(1) Worst case scenario
(2) Best case scenario
(3) Average situation
We use a random selection method for the benchmark p, which can prove that the complexity of quick sort in the average case is
4. Algorithm description
private static int partition (int p, int r) { int i = p, j = r 1; Comparable x = a[p]; //Fixed selection of the first element as pivot // Swap the elements of <x to the left area // Swap the elements >x to the right area while (true) { while (a[ i].compareTo(x) < 0 && i<r); while (a[--j].compareTo(x) > 0); if (i >= j) break; MyMath.swap(a, i, j); } a[p] = a[j]; a[j] = x; return j; } private static int randomizedPartition (int p, int r) { int i = random(p,r); MyMath.swap(a, i, p); return partition (p, r); }
2.9 Linear time selection
1. Introduction to the problem
Given an array from smallest to largest: a[1] a[2] ... a[k] ... a[n] It is required to find the kth smallest element. k (1<=k<=n)
2. Algorithm ideas
· Randomly select a pivot
· Move forward if it is smaller than pivot, and move backward if it is larger than pivot.
· After one round, divide the array according to pivot, and know the pivot number j. If you want to select the kth smallest number, there are three situations:
(1) k = j: This is the number to be selected, exit the algorithm
(2) k < j: Recursively solve the left sub-problem
(3) k > j: Recursively solve the right sub-problem
3. Complexity analysis
· Worst time complexity
· Average time complexity
4. Algorithm improvements
(1 Introduction
If a division criterion can be found in linear time such that the lengths of the two subarrays divided according to this criterion are at least ε times the length of the original array (0 < ε < 1), then you can use O(n) time to complete the selection task
(2) Steps
· For a group of 5 elements, divide the n input elements into ⌈n/5⌉ groups (the last group may be less than 5 elements). Sort the elements in each group using any algorithm, and take the median of each group, a total of ⌈n/5⌉ ~ O(n)
· Recursively call select to find the median of these ⌈n/5⌉ medians of each group as pivot x ~ T(n/5)
· Divide 2 subarrays by x ~ O(n)
· Based on the comparison result between the ordinal number of the pivot and the ordinal number currently to be selected, the selection algorithm is recursively called on the subarray ~ T(3n/4)
(3) Analysis
· The base x is at least larger than ë3(n - 5)/10û elements (red)
· The base x is at least smaller than ë3(n - 5)/10û elements (green)
· When n>=75, ë3(n - 5)/10û>=n/4, so the length of the two subarrays divided according to this criterion is shortened by at least 1/4
(4) Complexity
5. Algorithm description
private static Comparable randomizedSelect(int p,int r,int k) { if (p==r) return a[p]; int i = randomizedpartition(p,r), j = i-p 1; if (k<=j) return randomizedSelect(p,i,k); else return randomizedSelect(i 1,r,k-j); } private static Comparable select (int p, int r, int k) { if (r-p<5) { //Use a simple sorting algorithm to sort the array a[p:r]; bubbleSort(p,r); return a[p k-1]; } //Find the median of each group //Exchange the third smallest element from a[p 5*i] to a[p 5*i 4] with a[p i]; r-p-4 is the n-5 mentioned above for ( int i = 0; i<=(r-p-4)/5; i ) { int s=p 5*i, t=s 4; for (int j=0;j<3;j ) bubble(s,t-j); //bubble is a round of bubbles in bubbleSort MyMath.swap(a, p i, s 2); } //Find the median of the median, Comparable x = select(p, p (r-p-4)/5, (r-p 6)/10); int i=partition(p,r,x), j=i-p 1; if (k<=j) return select(p,i,k); else return select(i 1,r,k-j); }
2.10 Closest point pair problem(*)
2.11 Round Robin Schedule
1. Problem description
Design a round-robin competition schedule that meets the following requirements: (1) Each player must compete once with other n − 1 players. (2) Each player can only compete once a day (3) The round robin lasts for n − 1 days in total
2. Algorithm ideas
Divide all the players in half, and the game schedule for n (take 2k) players can be determined by designing the game schedule for n/2 players. By recursively dividing the players until only 2 players are left, the game schedule becomes simple. At this time, just let these two players compete.
3. Diagram
Chapter 3 Dynamic Programming
3.1 Matrix multiplication problem
1. Explore the problem
When multiple matrices are multiplied, the order of the products will affect the number of calculations. As shown in the picture
2. Introduction to the problem
Given n matrices {A1, A2,⋯ , An}, where Ai and Ai 1 are multiplicable, i = 1, 2,..., n − 1. Gives the sequence of matrices with the least number of multiplications
3. Exhaustive method
(1) Algorithm idea
List all possible calculation orders, calculate the number of multiplications required for each calculation order, and find a calculation order with the least number of multiplications.
(2) Algorithm process
· Let P(n) be the number of consecutive multiplications of n matrices in different calculation orders.
· The outermost layer is combined at k and is divided into 2 sub-problems:
· Recursive calculation
(3) Recursion formula
(4) Solve
4. Dynamic programming solution
(1) Premise
· AiAi 1...Aj(i<=j) is abbreviated as A[i:j]
(2) Structural characteristics of the optimal solution
The calculation order of the matrix subchains A[i : k] and A[k 1 : j] included in the optimal calculation order of A[i : j] must also be optimal.
(3) Establish a recursive relationship
Using m[i, j] to represent the minimum number of multiplications required to calculate A[i : j] (1<=i<=j<=n), the following recursive relationship is established:
(4) Overlapping sub-problems
When solving the recursive algorithm, the overlapping subproblems are repeatedly calculated multiple times:
Solution: form filling method (non-recursive), with memo (recursive)
(5) Algorithm description
public static void matrixChain(int [] p, int [][] m, int [][] s) { int n=p.length-1; for (int i = 1; i <= n; i ) m[i][i] = 0; for (int r = 2; r <= n; r ) for (int i = 1; i <= n - r 1; i ) { int j=i r-1; m[i][j] = m[i 1][j] p[i-1]*p[i]*p[j]; s[i][j] = i; for (int k = i 1; k < j; k ) { int t = m[i][k] m[k 1][j] p[i-1]*p[k]*p[j]; if (t < m[i][j]) { m[i][j] = t; s[i][j] = k; } } } } int RecurMatrixChain(int i, int j) { if (i==j) return 0; int u=RecurMatrixChain(i, i) RecurMatrixChain(i 1, j) p[i-1]*p[i]*p[j]; s[i][j]=i; for (int k = i 1; k < j; k ) { int t =RecurMatrixChain(i, k) RecurMatrixChain(k 1, j) p[i-1]*p[k]*p[j]; if (t < u) { u = t; s[i][j] = k; } } return u; } a <- 0; // m is initialized to all 0s before execution private static int lookupChain(int i, int j) { if (m[i][j] > 0) return m[i][j]; //Memo has been made if (i == j) return 0; int u = lookupChain(i 1,j) p[i-1]*p[i]*p[j]; s[i][j] = i; for (int k = i 1; k < j; k ) { int t = lookupChain(i,k) lookupChain(k 1,j) p[i-1]*p[k]*p[j]; if (t < u) { u = t; s[i][j] = k; } } m[i][j] = u; return u; }
(6) Complexity analysis
· time complexity
· Space complexity
3.2 Basic elements of dynamic programming algorithm
1. Two major elements
(1) Optimal substructure characteristics
The optimal solution to a large-scale problem contains the optimal solutions to its sub-problems
(2) Overlapping sub-problem characteristics
When decomposing a problem, the same subproblems are generated repeatedly
2. Optimal substructure
(1) How to analyze the optimal substructure properties of the problem? proof by contradiction
First assume that the sub-problem solution derived from the optimal solution to the original problem is not optimal, and then explain that a better solution than the optimal solution to the original problem can be constructed at this time, so there is a contradiction.
(2) How to utilize optimal substructure properties? Construct a recurrence relation
The optimal solution of the entire problem is gradually constructed from the optimal solution of the sub-problem in a bottom-up recursive manner.
3.3 Longest common subsequence
1. Problem description
Given 2 sequences: X = {x1, x2,..., xm} Y = {y1, y2,..., yn} Find the longest common subsequence of X and Y (Longest Common Sequence)
2. Application examples
· Plagiarism code detection system
·Web page keyword search
·DNA sequence matching
·Audio recognition system
3. Problem analysis
(1) Premise
Let the sequence X = {x1, x2,..., xm} Y = {y1, y2,..., yn} The longest common subsequence of is Z = {z1, z2,..., zk}
(2) Symbol convention
· Xi represents the prefix of X, that is, Xi = {x1, x2,..., xi}
· Yj: prefix of Y Yj = {y1, y2,..., yj}
· Use LCS(.,.) to calculate the longest common subsequence
· Use c[i][j] to represent the length of the longest common subsequence of Xi and Yj
(3) Situation analysis
· m = 0 or n = 0
· xm = ym (the last elements are equal)
· xm != ym (the last elements are not equal)
Then LCS[Xm][Yn] is equal to the larger of the following two: · The longest common subsequence LCS(Xm-1, Yn) of Xm-1 and Yn · The longest common subsequence LCS(Xm, Yn-1) of Xm and Yn-1
(4) Recursion formula
(5) Algorithm description
Algorithm lcs(int i,int j,char [] x,int [][] b) { if (i ==0 || j==0) return; if (b[i][j]== 1){ lcs(i-1,j-1,x,b); System.out.print(x[i]); } else if (b[i][j]== 2) lcs(i-1,j,x,b); else lcs(i,j-1,x,b); } Algorithm lcsLength(x,y,b) { m <- x.length-1; n <- y.length-1; c[1..m][0]=0; c[0][1..n]=0; for (int i = 1; i <= m; i ) for (int j = 1; j <= n; j ){ if (x[i]==y[j]) { c[i][j]=c[i-1][j-1] 1; b[i][j]=1; } else if (c[i-1][j]>c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2; } else { c[i][j]=c[i][j-1]; b[i][j]=3; } } }
(6) Complexity analysis
In the subproblem space considered, there are a total of Θ(mn) different subproblems, so Therefore, the size of the subproblem is polynomial. When dynamic programming algorithm is used to iteratively calculate the optimal value from the bottom up, only different sub-problems, which can improve the efficiency of the algorithm
3.4 Optimal triangulation of convex polygons
1. Basic concepts
Convex polygon: P = {v0, v1, ..., vn-1} · n edges vivi 1 (v0 = vn) · Line segment vivj (vi and vj are not adjacent) chord · A chord divides the polygon into 2 polygons: {vi, vi 1, ..., vj}, {vj, vj 1, ...,vi}
2. Triangulation
(1) Concept
Split the polygon into Disjoint triangles The set of strings of shape T
(2) Nature
· The strings do not intersect each other, and the set T has reached the maximum
· There are exactly n - 3 chords and n - 2 triangles
3. The concept of weight function
The weight function w(·) of a triangle can be defined in various ways, for example
4. Problem description
All possible triangulations of a convex polygon are denoted as a set F, and the triangulation with the smallest weight among them is found.
5. Optimal substructure
If the convex polygon T is the optimal triangulation and is divided into two parts T1 and T2, then T1 and T2 must be the optimal triangulation of the sub-polygon and satisfy:
6. Algorithm ideas
(1) j = i
The convex polygon {vi-1, vi} degenerates into a straight line with weight t[i][j] = 0 (recursive exit)
(2)j>i
The convex subpolygon {v-1i, vi, ..., vj} has at least 3 vertices, triangulation exists, and the weight of the optimal triangulation is t[i][j]
7. Recursion formula
8. Complexity analysis
(1) Time complexity
(2) Space complexity
3.5 Polygon Games
1. Gameplay
(1 Introduction
In a polygon with n vertices, each vertex is assigned an integer (which can be negative) and each edge is assigned the operator or *, with the edges numbered sequentially from 1 to n
(2) Rules
· Step 1, delete an edge
· Then n - 1 steps are performed as follows: A. Select an edge E (its vertices are set to V1 and V2) B. Replace edge E and vertices V1 and V2 with a new vertex, assigning the integer values of vertices V1 and V2 to the new vertex as a result of the operation on edge E C. All edges are deleted and the game is over D. The score of the game is the integer value of the remaining vertices.
(3) Question
For a given polygon, calculate the highest score
(4) Example
2. Problem analysis
(1) Optimal substructure properties
A chain P(i, j) of length j starting from vertex i (that is, having j vertices)
If the last merge operation in its optimal solution occurs at edge op[i s] (1<=s<=j-1), then the original chain at op[i s] will be divided into two sub-chains
(2) Recursive structure of solution
3.6 Image compression
1. Image displacement compression storage format
· Divide n pixels into m continuous segments {Si}m
·
·
2. Problem description
Determine the optimal segment S' of the pixel sequence <p1, p2, ..., pn>, which requires the least storage space
3. Problem analysis
(1) Optimal substructure properties
Assume that the optimal segment of <p1, p2, ..., pn> is {Si}m, and the length of the m-th segment Sm is l[m], then {Si}m-1 is a subproblem< The optimal segmentation of p1, p2, ..., pn-l[m]>
(2) Recursive formula
(3) Complexity analysis
· time complexity
· Space complexity
3.7 Optimal Binary Search Tree
1. Basic concepts
2. Problem description
3. Results of brute force solution
4. Optimal substructure properties
(1) Description
(2) Proof
5. Recursive formula
6. Complexity analysis
(1) The complexity of this algorithm
(2) Improve algorithm
Chapter 4 Greedy Algorithm
4.1 Event arrangement issues
1. Problem description
There is a set of n activities E = {1, 2, ..., n}, activity i occupies resources within the duration, and different activities will have time conflicts and are incompatible. Find the largest sub-set of consistent activities from the set of activities.
2. Algorithm description
(1) Steps
· First sort the activities in non-decreasing order by end time
· Then start greedy selection from activity 1
(2) Part of the code
public static int greedySelector(int[] s, int[] f, boolean a[]) //The start and end times of each activity are stored in the arrays s and f, and are arranged in non-decreasing order of the end time { int n=s.length-1; a[1]=true; int j=1; int count=1; for (int i=2;i<=n;i) { if (s[i]>=f[j]) { //Select if compatible a[i]=true; j=i; count ; } else a[i]=false; //incompatible } return count; }
3. Complexity analysis
1. Excluding sorting time, the algorithm complexity is O(n)
2. Including the sorting time, the algorithm complexity is O(nlogn)
4. Proof of correctness of greedy algorithm
4.2 Basic elements of greedy algorithm
1. The nature of greedy selection
2. Optimal substructure properties
3. Comparison between greedy algorithm and dynamic programming
(1) Common points
All have optimal substructures
(2) Differences
dynamic programming
Keep solutions to all subproblems
greedy algorithm
Only solve the optimal solution of a sub-problem determined according to the greedy strategy, and only retain one solution path
4.3 Optimal loading
1. Problem description
A batch of containers is to be loaded onto a ship with a carrying capacity of c. in The weight of container i is wi. not exceeding the carrying capacity of the ship Load as many containers as possible onto the ship.
2. The nature of greedy selection
(1) Description
Each selection is from the smallest weight among the remaining containers until the total load is the maximum value that does not exceed the capacity limit.
(2) Proof
3. Optimal substructure properties
(1) Description
(2) Proof
4. Algorithm description
public static float loading(float c, float [] w, int [] x) { int n=w.length; Element [] d = new Element [n]; for (int i = 0; i < n; i ) d[i] = new Element(w[i],i); MergeSort.mergeSort(d); float opt=0; for (int i = 0; i < n; i ) x[i] = 0; for (int i = 0; i < n && d[i].w <= c; i ) { x[d[i].i] = 1; opt =d[i].w; c -= d[i].w; } return opt; }
5. Complexity analysis
The main time load of loading is sorting, ~ O(nlogn)
4.4 Huffman coding
1. Huffman coding
According to the frequency of characters appearing in the file, establish an optimal representation method using a string of 0 and 1 to represent each character.
2. Basic idea
Characters that appear frequently have shorter codes, and characters that appear less frequently have longer codes.
3. Basic concepts
(1) Prefix code
For each character of character set C, a string of 0, 1 is specified as its code, and the code of any character is required not to be a prefix of other character codes. Advantages: Simple decoding method
(2) Coding tree
The prefix code can be expressed as a complete binary tree (that is, any internal node in the tree has 2 child nodes)
(3) Average code length
(4) Optimal prefix code
4. Huffman coding example
5. Greedy thoughts
Construct a binary tree T representing the optimal prefix code from the bottom up
6. Algorithm description
7. Complexity Analysis
8. Proof of correctness
(1) The nature of greedy selection
· describe
· prove
(2) Optimal substructure
· describe
· prove
Chapter 5 Backtracking
5.1 Algorithmic framework of backtracking method
1. Basic concepts
(1) State space
(2) Constraint definition
· Display constraints
Value limits for components
· Implicit constraints
Constraints between different components
(3) Completeness characteristics
2. Solution space of the problem
(1) Solution vector
The solution to the problem can be represented by an n-element vector (x1, x2, ... xn)
(2) Solution space
For a problem instance, all solution vectors that satisfy the display constraints constitute a solution space for the problem instance.
3. Several basic concepts
(1) Slipknot
A node that has itself been generated but all its children have not yet been generated.
(2) Extension node
Among live nodes, a node that is producing a son is called an extension node.
(3) Dead node
Node that is not being expanded
4. Backtracking method
5. Pruning
6. Recursive backtracking
7. Iterative backtracking
8. Space complexity
The backtracking method dynamically generates the solution space of the problem during the search process, and only saves the path from the root node to the current expansion node, with a space complexity of O(h(n))
9. Two solution space structures
(1) Subset tree (combination problem)
· describe
· Recursive algorithm
· Algorithm description
(2) Arrangement tree (arrangement problem)
· describe
· Recursive algorithm
· Algorithm description
5.2 Loading issues
1. Problem description
2. Problem analysis
3. Solution space
subset tree
4. Pruning function
5. Algorithm description
private static void backtrack (int i) {//Search for the i-th layer node if (i > n) { // Reach the leaf node Update the optimal solution bestx, bestw; return; } r -= w[i]; //try to load i if (cw w[i] <= c){ //Loading i cannot be overweight - constraints. Thinking: Why is there no limit function here? ? ? ? ? ? // Search left subtree (load i) x[i] = 1; cw = w[i]; backtrack(i 1); cw -= w[i]; //Undo the loading of i and prepare data for analysis without loading i!!!!!!!!!! } else{ //Prune, do nothing here } //Try not to load i if (cw r > bestw){ //The total weight w[i 1..n] after i must be heavy enough——limiting conditions x[i] = 0; // Search the right subtree (without i) backtrack(i 1); } else{ //Prune, do nothing here } r = w[i]; }
6. Time complexity
O(2n)
5.3 Batch job scheduling
1. Basic concepts
2. Problem description
3. Example
4. Algorithm ideas
5. Algorithm description
public class FlowShop{ static int n; //Number of jobs static int f1; // Machine 1 completes processing time static int f; //sum of completion time static int bestf; // current best value static int [][] m; // The processing time required for each job static int [] x; // Current job schedule static int [] bestx; // Current optimal job scheduling static int [] f2; // Machine 2 completes processing time private static void backtrack(int i) { //Main program framework: Recursive algorithm to generate n full arrangements if (i > n) { for (int j = 1; j <= n; j ) // Save the current best minx[j] = x[j]; bestf = f; } else for (int j = i; j <= n; j ) { //Detect x[i]...x[n] in sequence f1 = m[x[j]][1]; // f2[i] = ((f2[i-1]>f1) ? f2[i-1] : f1) m[x[j]][2]; f = f2[i]; if (f < minf) { // Boundary conditions MyMath.swap(x,i,j); backtrack(i 1); MyMath.swap(x,i,j); } f1 -= m[x[j]][1]; f -= f2[i]; } } }
5.4 Symbolic triangle problem
1. Problem description
There are n symbols in the first row. Count how many different symbol triangles there are.
2. Algorithm design
3. Algorithm ideas
4. Algorithm description
//Search for the i-th subtree in the solution space private static void backtrack (int t) { if ((count>half)||(t*(t-1)/2-count>half)) // or - the number exceeds half, prune return; if (t>n) sum ; // It is a feasible symbolic triangle, and the number of feasible solutions (sum) is accumulated else for (int i=0;i<2;i) { //The added symbol on the right side of the first line is 0 ("-") or 1 (" ") p[1][t]=i; count =i; // number of " " for (int j=2;j<=t;j ) { // p[j][t-j 1]=p[j-1][t-j 1]^p[j-1][t-j 2]; // Same or count =p[j][t-j 1]; } backtrack(t 1); for (int j=2;j<=t;j) //restore to t count-=p[j][t-j 1]; count-=i; } }
5. Complexity analysis
5.5 n-queen problem
1. Problem description
On a chessboard with n × n squares Place n that are immune to each other queens, that is, any 2 Queens are not placed in the same row or in the same row in a column or on the same slash
2. Solution space representation
3. Pruning
4. Concept
5. Algorithm description
5.6 0-1 knapsack problem
1. Algorithm idea
2. Dynamic tree solution method
Chapter 6 Branch and Bound Method
6.1 Basic idea
1. Search process
2. Two common branch and bound methods
6.2 Single-source shortest path problem
1. Problem description
2. Algorithm process
subtopic
3. Algorithmic thinking
priority
The node with the longest current path and the smallest intersection will be given priority.
data structure
Min-heap as a priority queue for live nodes
4. Algorithm description
public static void shortest(int v, float [] dist, int [] p) { //Detailed code omitted... //The code of the core part is as follows while(true) { // Search the solution space of the problem for (int j=1;j<=n;j ) // There is an edge between vertices i and j, and the path length is smaller than the original path length from source point s to j if (a[enode.i][j] < Float.MAX_VALUE && enode.length a[enode.i][j] < dist[j]) { // Vertex i is reachable from vertex j and satisfies control constraints dist[j]=enode.length a[enode.i][j]; p[j]=enode.i; HeapNode node = new HeapNode(j,dist[j]); heap.put(node); // Join the live node priority queue //A node in the graph may be added multiple times } if (heap.isEmpty()) break; else enode = (HeapNode) heap.removeMin(); } }
6.3 Loading issues
1. Problem description
2. Problem analysis
3. Two ideas
· Queued branch limits
· Priority queue branch bounding
4. Queue branch and bound method
· Pruning function
· Algorithm Description
·Construct optimal solution
5. Priority queue branch and bound method
6.4 Cabling issues
1. Problem description
2. Algorithmic thinking
3. Example
4. Complexity analysis
6.5 0-1 knapsack problem
1. Algorithmic thinking
2. Upper bound function
private static double bound(int i) { //Use fractional backpack to estimate the upper bound for items after i double cleft = c - cw; //remaining capacity double b = cp; //value upper bound while (i <= n && w[i] <= cleft) {//n represents the total number of items, cleft is the remaining space cleft -= w[i]; //w[i] represents the space occupied by i b = p[i]; //p[i] represents the value of i i; } if (i <= n) b = p[i] / w[i] * cleft; // Fill the remaining capacity to fill the backpack return b; // b is the upper bound function }
3.bbKnapsack
private static double BBKnapsack() {//Priority queue type branch limit, return the maximum value, bestx returns the optimal solution //Variable definition (omitted)... while (i != n 1) {// non-leaf node //Check the left child node: add the i-th item double wt = cw w[i]; if (wt <= c) {//Constraints //The left son node is a feasible node if (cp p[i] > bestp) bestp = cp p[i]; addLiveNode(up,cp p[i],cw w[i],i 1, enode, true); //Join the live node priority queue } up = bound(i 1); //Check the right child node: do not add the i-th item if (up >= bestp) //upper bound condition addLiveNode(up,cp, cw, i 1, enode, false); //Join the live node priority queue // Remove the next extension node HeapNode node=(HeapNode) heap.removeMax(); cw = node.weight; cp = node.profit; up = node.upperProfit; i =node.level; } //Construct the current optimal solution (omitted)... }
Design and Analysis of Algorithms
Chapter 1 Introduction to Algorithms
Chapter 2 Recursion and Divide and Conquer Strategy
Chapter 3 Dynamic Programming
Chapter 4 Greedy Algorithm
Chapter 5 Backtracking
Chapter 6 Branch and Bound Method