Ten algorithms commonly used by programmers

Keywords: Algorithm data structure

1. Binary search algorithm (non recursive implementation)

1.1 introduction to binary search algorithm (non recursive)

  1. We have known about the binary search algorithm before, but the recursive implementation is used. Next, we understand the non recursive implementation of the binary search algorithm

  2. (note): the binary search algorithm is only applicable to ordered sequences. For unordered sequences, we need to sort them first.

  3. The running time of bisection search algorithm 1 is logarithmic time O(㏒Λn), that is, it only takes ㏒Λn steps to find the target location at most.

1.2 non recursive code implementation of binary search algorithm

public class BinarySearchNoRecur {
    public static void main(String[] args) {
        int[] arr = {1, 3, 8, 10, 11, 67, 100};
        int index = binarySearch2(arr, -100, 0, arr.length - 1);
        System.out.println("index=" + index);//
    //Non recursive implementation of binary search
     * @param arr    The array to be searched, arr is sorted in ascending order
     * @param target Number of to find
     * @return Return the corresponding subscript, - 1 means it is not found
    public static int binarySearch(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) { //Description continue to find
            int mid = (left + right) / 2;
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] > target) {
                right = mid - 1;//You need to look to the left
            } else {
                left = mid + 1; //You need to look to the right
        return -1;
    //Recursive implementation of binary search
    public static int binarySearch2(int[] arr, int target, int left, int right) {
        int mid = (left + right) / 2;
        if (target == arr[mid]) {
            return mid;
        if (left < right){
            if (arr[mid] > target) {
                return binarySearch2(arr, target, left, mid - 1);
            } else if (arr[mid] < target) {
                return binarySearch2(arr, target, mid + 1, right);
        }else {
            return -1;
        return -1;

2. Divide and conquer algorithm

2.1 introduction to divide and conquer algorithm

1) Divide and conquer algorithm is a very important algorithm. The literal explanation is "divide and conquer", which is to divide a complex problem into two or more identical or similar subproblems, and then divide the subproblem into smaller subproblems ~ ~ ~ know that the final subproblem can be solved simply and directly, and the solution of the original problem is the combination of the solutions of the subproblems. This technique is the basis of many efficient algorithms, such as sorting algorithm (fast sorting, merge sorting), Fourier transform (fast Fourier transform)

2) Divide and conquer algorithm can solve some classical problems

  • Binary search

  • Large integer multiplication

  • Chessboard coverage

  • Merge sort

  • Quick sort

  • Linear time selection

  • Closest point pair problem

  • Round robin schedule

  • Hanoi

2.2 basic steps of divide and conquer algorithm

Divide and conquer has three steps at each level of recursion

  1. Decomposition: decompose the original problem into several small-scale, independent sub problems with the same form as the original problem

  2. Solution: if the subproblem is small and easy to be solved, solve it directly, otherwise solve each problem recursively

  3. Merge: merge the solutions of each sub problem into the solutions of the original problem

2.3 divide and conquer algorithm practice - Tower of Hanoi

  • Legend of the tower of Hanoi

    Hanoi Tower: the problem of Hanoi Tower (also known as Hanoi Tower) is an educational toy derived from an ancient Indian legend. When Brahma created the world, he made three diamond pillars. On one pillar, 64 gold discs were stacked in order of size from bottom to top. Brahma ordered Brahman to rearrange the disk on another column in order of size from below. It is also stipulated that the disc cannot be enlarged on the small disc, and only one disc can be moved between the three columns at a time. If every second, how long does it take? It takes more than 584.554 billion years to remove these gold pieces, and the life expectancy of the solar system is said to be tens of billions of years. After 584.554 billion years, all life on earth, including Vatican pagodas and temples, has long been extinguished.

  • Analysis on the thinking of Hanoi Tower

    1) If there is a disk, a - > C

    If we have n > = 2, we can always look at two disks, 1. The bottom disk and 2. The top disk

    2) First put the top plate a - > B

    3) Put the lowest disk a - > C

    4) Remove all trays of Tower B from B - > C

2.4 code implementation

public class Hanoitower {
    public static void main(String[] args) {
        hanoiTower(10, 'A', 'B', 'C');
    //Method of moving Hanoi Tower
    //Using divide and conquer algorithm
    public static void hanoiTower(int num, char a, char b, char c) {
        //If there is only one disk
        if(num == 1) {
            System.out.println("1st disk from " + a + "->" + c);
        } else {
            //If we have n > = 2, we can always be regarded as two disks 1. The lowest disk 2. All disks above
            //1. First put all the uppermost disks a - > b, and c will be used in the moving process
            hanoiTower(num - 1, a, c, b);
            //2. Turn the lowest disc a - > C
            System.out.println("The first" + num + "Disk from " + a + "->" + c);
            //3. Move all trays of Tower B from B - > C to tower a
            hanoiTower(num - 1, b, a, c);

3. Dynamic programming algorithm

3.1 application scenario - Knapsack Problem

Knapsack problem: there is a knapsack with a capacity of 4 pounds, and now there are the following items

Guitar (G)11500
Audio (S)43000

1) The goal to be achieved is to maximize the total value of the loaded backpack and not exceed the weight

2) The items required to be loaded cannot be repeated

3.2 introduction to dynamic programming algorithm

  1. The core idea of dynamic programming algorithm is to divide large problems into small problems for solution, so as to further obtain the optimal solution

  2. Dynamic programming algorithm is similar to divide and conquer algorithm. Its basic idea is to decompose the problem to be solved into several sub problems. First solve the sub problems, and then get the solution of the original problem from the solutions of these sub problems.

  3. The difference with divide and conquer method is that it is suitable for problems solved by dynamic programming, and the subproblems obtained by decomposition are often not independent of each other. (that is, the solution of the next sub stage is based on the solution of the previous sub stage for further solution)

  4. Dynamic programming can be advanced step by step by filling in tables to obtain the optimal solution.

3.3 practice of dynamic programming algorithm knapsack problem

There is a backpack with a capacity of 4 pounds and the following items are available

Guitar (G)11500
Audio (S)43000
  1. The goal to be achieved is to maximize the total value of the loaded backpack and not exceed the weight

  2. The items required to be loaded cannot be repeated

3.4 thought analysis and code implementation

  • Knapsack problem mainly refers to a given capacity knapsack and several items with certain value and weight. How to select items to put into the knapsack to maximize the value of items. It is divided into 01 backpack and complete backpack (complete backpack means that there are unlimited items available for each item)

  • The problem here belongs to 01 backpack, that is, put one item at most. The infinite backpack can be transformed into 01 backpack.

  • The main idea of the algorithm is solved by dynamic programming. For the i-th item traversed each time, determine whether to put the item into the backpack according to w[i] and v[i]. That is, for a given n items, let v[i] and w[i] be the value and weight of the ith item respectively, and C be the capacity of the backpack. Re order v i Indicates the maximum value of the first i items that can be loaded into a backpack with a capacity of j. Then we have the following results:

(1) v[i] [0]=v[0] [j]=0; // Indicates that the first row and the first column of the filled table are 0 (2) when w [i] > J: v [i] [J] = v[i-1] [j] / / when the capacity of the new product to be added is greater than the capacity of the current backpack, the loading strategy of the previous cell is directly used (3) when J > = w [i]: v[i] [j]=max{v[i-1] [j], v[i]+v[i-1] [j-w[i]]} //When the capacity of the newly added commodity to be added is less than or equal to the capacity of the current backpack, / / loading method: v[i-1] [j]: is the maximum loading value of the previous cell v [i]: represents the value of the current commodity v[i-1] [j-w[i]]: load the i-1 commodity to the maximum value of the remaining space j-w[i]. When J > = w [i]: v i=max{v[i-1] [j], v[i]+v[i-1] [j-w[i]]}


Code implementation:

public class KnapsackProblem {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] w = {1, 4, 3};//Weight of articles
        int[] val = {1500, 3000, 2000}; //Value of goods here val[i] is v[i] mentioned earlier
        int m = 4; //Backpack Capacity
        int n = val.length; //Number of items
        //Create a two-dimensional array,
        //v[i][j] represents the maximum value that can be loaded into a backpack with a capacity of j in the first I items
        int[][] v = new int[n+1][m+1];
        //In order to record the placement of goods, we set up a two-dimensional array
        int[][] path = new int[n+1][m+1];
        //Initialize the first row and the first column. In this program, you can not handle it, because the default is 0
        for(int i = 0; i < v.length; i++) {
            v[i][0] = 0; //Set the first column to 0
        for(int i=0; i < v[0].length; i++) {
            v[0][i] = 0; //Set the first row to 0
        //According to the previous formula to deal with dynamic programming
        for(int i = 1; i < v.length; i++) { //Do not process the first line i, which starts with 1
            for(int j=1; j < v[0].length; j++) {//Do not process the first column, j starts with 1
                if(w[i-1]> j) { // Because our program I starts from 1, w[i] in the original formula is modified to w[i-1]
                } else {
                    //Because our i starts with 1, the formula needs to be adjusted to
                    //v[i][j]=Math.max(v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]);
                    //v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);
                    //In order to record the goods stored in the backpack, we can't directly use the above formula. We need to use if else to reflect the formula
                    if(v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
                        v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
                        //Record the current situation to path
                        path[i][j] = 1;
                    } else {
                        v[i][j] = v[i - 1][j];
        //Output it v to see the current situation
        for(int i =0; i < v.length;i++) {
            for(int j = 0; j < v[i].length;j++) {
                System.out.print(v[i][j] + " ");
        //Output which goods we put in at the end
        //Traverse the path, so that the output will get all the loading conditions. In fact, we only need the last loading
//      for(int i = 0; i < path.length; i++) {
//          for(int j=0; j < path[i].length; j++) {
//              if(path[i][j] == 1) {
//                  System.out.printf("put the% d item into the backpack \ n", i);
//              }
//          }
//      }
        //Use your head
        int i = path.length - 1; //Maximum subscript of row
        int j = path[0].length - 1;  //Maximum subscript of column
        while(i > 0 && j > 0 ) { //Start at the end of the path
            if(path[i][j] == 1) {
                System.out.printf("The first%d Put items into the backpack\n", i);
                j -= w[i-1]; //w[i-1]

4. KMP algorithm

4.1 application scenario - string matching problem

  • String matching problem

    • There is a string str1 = "" Silicon Valley is still Silicon Valley, you are still Silicon Valley, you are still Silicon Valley, you are still Silicon Valley, you are still silicon hello "", and a substring str2 = "still Silicon Valley, you are still silicon you"

    • Now it is necessary to determine whether str1 contains str2. If it exists, it returns the first occurrence position. If not, it returns - 1

4.2 violence matching algorithm

If we use the idea of violent matching and assume that str1 is now matched to position i and substring str2 is matched to position j, there are:

  • If the current character matches successfully (i.e. str1[i] == str2[j]), I + +, j + +, continue to match the next character

  • If mismatch (i.e. str1[i]! = str2[j]), let i = i - (j - 1), j = 0. It is equivalent to I backtracking and J being set to 0 every time a match fails.

  • If violence is used to solve the problem, there will be a lot of backtracking. Only move one bit at a time. If it doesn't match, move to the next bit and judge. It wastes a lot of time. (not feasible!)

  • Violent matching algorithm implementation

public class ViolenceMatch {
    public static void main(String[] args) {
        String str1 = "Silicon valley still Silicon Valley you still Silicon Valley you still Silicon Valley you still Silicon Valley you still silicon hello";
        String str2 = "Shang Silicon Valley you Shang silicon you 1";
        int index = violenceMatch(str1, str2);
        System.out.println("index = " + index);
    public static int violenceMatch(String str1,String str2) {
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();
        int s1Len = s1.length;
        int s2Len = s2.length;
        int i = 0;
        int j = 0;
        while (i < s1Len && j < s2Len) {
            if (s1[i] == s2[j]) {
            }else {
                i = i - j + 1;
                j = 0;
        if (j == s2Len) {
            return i - j;
        }else {
            return -1;

4.3 introduction to KMP algorithm

1) KMP is a classical algorithm to solve whether the pattern string has appeared in the text string, and if so, the earliest position. 2) Knuth Morris Pratt string search algorithm, referred to as "KMP algorithm", is often used to find the occurrence position of a pattern string P in a text string S. This algorithm is composed of Donald Knuth, Vaughan Pratt James H. Morris jointly published in 1977, so they named the algorithm after their surnames. 3) KMP algorithm uses the previously judged information to save the length of the longest common subsequence in the pattern string through a next array. During each backtracking, it finds the previously matched position through the next array, saving a lot of calculation time. 4) reference: Very detailed KMP algorithm (powerful) - ZzUuOo666 - blog Park

4.4 best application of KMP algorithm - string matching problem

String matching problem: 1) there is a string str1 = "BBC abcdab abcdabde" and a substring str2="ABCDABD" 2) now it is necessary to judge whether str1 contains str2. If it exists, it will return the first occurrence position. If not, it will return - 1. 3) requirements: use KMP algorithm to complete the judgment, and simple violent matching algorithm cannot be used

Train of thought analysis diagram

For example, there is a string Str1 = "BBC abcdab abcdabde", judge whether it contains another string Str2 = "ABCDABD"?

  1. First, compare the first character of Str1 with the first character of Str2. If it does not match, the keyword moves back one bit


  1. Repeat the first step, if it still does not meet the requirements, move it back


  1. Repeat until one character of Str1 matches the first character of Str2


  1. Then compare the string with the next character of the search term, and it still matches.


  1. Encountered a character in Str1 that does not match the character corresponding to Str2


  1. At this time, the thought is to continue to traverse the next character of Str1 and repeat step 1. (actually, it is very unwise, because BCD has been compared at this time, and there is no need to do repeated work. A basic fact is that when the space does not match D, you actually know that the first six characters are "ABCDAB". The idea of KMP algorithm is to try to use this known information, do not move the "search position" back to the position that has been compared, and continue to move it back, This improves efficiency.)


  1. How to omit the steps just repeated? A partial matching table can be calculated for Str2. The generation of this table will be described later


  1. When it is known that the space does not match D, the first six characters "ABCDAB" match. It can be seen from the table that the "partial matching value" corresponding to the last matching character B is 2. Therefore, calculate the number of backward moving digits according to the following formula: moving digits = number of matched characters - corresponding partial matching value. Because 6 - 2 is equal to 4, move the search term backward by 4 digits.

  1. Because the space does not match C, the search term will continue to move back. At this time, the number of matched characters is 2 ("AB"), and the corresponding "partial matching value" is 0. Therefore, the number of moving bits = 2 - 0, and the result is 2, so move the search term back 2 bits.


  1. Continue to move back one bit because the space does not match A

  1. Compare bit by bit until C and D do not match. Then, move the number of digits = 6 - 2, and continue to move the search term backward by 4 digits.


  1. Compare bit by bit until the last bit of the search term, find an exact match, and the search is completed. If you want to continue the search (i.e. find all matches), move the digits = 7 - 0, and then move the search term back 7 digits, which will not be repeated here.

  1. Introduce how the partial matching table is generated. First introduce the prefix and suffix

"Partial match value" is the length of the longest common element of "prefix" and "suffix". Take "ABCDABD" as an example, the prefix and suffix of "A" are empty sets, and the length of common elements is 0; - " The prefix of "ab" is [A], the suffix is [B], and the length of common elements is 0; - " The prefix of "ABC" is [A, AB], the suffix is [BC, C], and the length of common elements is 0; - " The prefix of "ABCD" is [A, AB, ABC], the suffix is [BCD, CD, D], and the length of common elements is 0; - " The prefix of "ABCDA" is [A, AB, ABC, ABCD], the suffix is [BCDA, CDA, DA, A], the common element is "A", and the length is 1; - " The prefix of "ABCDAB" is [A, AB, ABC, ABCD, ABCDA], the suffix is [BCDAB, CDAB, DAB, AB, B], the common element is "ab", and the length is 2; - " The prefix of "ABCDABD" is [A, AB, ABC, ABCD, ABCDA, ABCDAB], the suffix is [BCDABD, CDABD, DABD, ABD, BD, D], and the length of common elements is 0.

  1. ”The essence of "partial match" is that sometimes there will be repetition at the beginning and end of the string. For example, if there are two "AB" in "ABCDAB", then its "partial matching value" is 2 (the length of "AB"). When the search term moves, the first "AB" moves back 4 bits (string length - partial matching value) to the position of the second "AB".


This is the end of KMP algorithm thought analysis!

4.5 representative realization

public class KMPAlgorithm {
    public static void main(String[] args) {
        String str1 = "BBC ABCDAB ABCDABCDABDE";
        String str2 = "ABCDABD";
        //String str2 = "BBC";
        int[] next = kmpNext("ABCDABD"); //[0, 1, 2, 0]
        System.out.println("next=" + Arrays.toString(next));
        int index = kmpSearch(str1, str2, next);
        System.out.println("index=" + index); // 15
    //Write our kmp search algorithm
     * @param str1 Source string
     * @param str2 Substring
     * @param next The partial matching table is the partial matching table corresponding to the substring
     * @return If it is - 1, there is no match. Otherwise, the first matching position is returned
    public static int kmpSearch(String str1, String str2, int[] next) {
        for(int i = 0, j = 0; i < str1.length(); i++) {
            //str1.charAt(i) needs to be processed= str2.charAt(j) to adjust the size of j
            //KMP algorithm core point, can verify
            while( j > 0 && str1.charAt(i) != str2.charAt(j)) {
                j = next[j-1];
            if(str1.charAt(i) == str2.charAt(j)) {
            if(j == str2.length()) {//Found / / j = 3 i
                return i - j + 1;
        return  -1;
    //Gets the partial matching value table of a string (substring)
    public static  int[] kmpNext(String dest) {
        //Create a next array to hold some matching values
        int[] next = new int[dest.length()];
        next[0] = 0; //If the string is a length of 1, the matching value is 0
        for(int i = 1, j = 0; i < dest.length(); i++) {
            //When dest.charat (I)= Dest. Charat (J), we need to get a new j from next[j-1]
            //We didn't quit until we found that dest.charAt(i) == dest.charAt(j) was established
            //This is the core of kmp algorithm
            while(j > 0 && dest.charAt(i) != dest.charAt(j)) {
                j = next[j-1];
            //When dest.charAt(i) == dest.charAt(j) is satisfied, the partial matching value is + 1
            if(dest.charAt(i) == dest.charAt(j)) {
            next[i] = j;
        return next;

5. Greedy algorithm

5.1 application scenario - set coverage problem

It is assumed that there are the following broadcasting stations that need to pay and the areas that can be covered by the broadcasting station signal. How to select the least number of broadcasting stations so that all regions can receive signals

  5.2 introduction to greedy algorithm

1) Greedy algorithm (greedy algorithm) refers to the algorithm that takes the best or optimal (i.e. the most favorable) choice in each step when solving the problem, so as to lead to the best or optimal result.

2) The results obtained by greedy algorithm are not necessarily the optimal results (sometimes the optimal solution), but they are relatively approximate (close) to the optimal solution

5.3 best application of greedy algorithm - set coverage

1) It is assumed that there are broadcasting stations that need to pay and areas that can be covered by broadcasting station signals in the following table. How to select the least number of broadcasting stations so that all regions can receive signals

  2) Train of thought analysis:

   how to find out the set of broadcasting stations covering all regions? Use the exhaustive method to list the set of each possible broadcasting station, which is called power set. false
If there are n broadcasting stations in total, there are 2 ⁿ - 1 broadcasting stations in total. It is assumed that 10 subsets can be calculated per second, as shown in the figure:

   greedy algorithm with high efficiency:
1) At present, there is no algorithm that can quickly calculate the prepared value. Using greedy algorithm, we can get a very close solution with high efficiency. In terms of policy, the minimum set covering all regions is required:
2) Traverse all radio stations and find a station that covers the most uncovered areas (this station may contain some covered areas, but it doesn't matter)
3) Add the radio station to a collection (such as ArrayList) and try to remove the areas covered by the radio station in the next comparison.
4) Repeat step 1 until all areas are covered


  Code implementation:

public class GreedyAlgorithm {

    public static void main(String[] args) {
        //Create a radio station and put it into the Map
        HashMap<String,HashSet<String>> broadcasts = new HashMap<String, HashSet<String>>();
        //Put each radio station into broadcasts
        HashSet<String> hashSet1 = new HashSet<String>();

        HashSet<String> hashSet2 = new HashSet<String>();

        HashSet<String> hashSet3 = new HashSet<String>();

        HashSet<String> hashSet4 = new HashSet<String>();

        HashSet<String> hashSet5 = new HashSet<String>();

        //Add to map
        broadcasts.put("K1", hashSet1);
        broadcasts.put("K2", hashSet2);
        broadcasts.put("K3", hashSet3);
        broadcasts.put("K4", hashSet4);
        broadcasts.put("K5", hashSet5);

        //allAreas stores all areas
        HashSet<String> allAreas = new HashSet<String>();

        //Create an ArrayList to store the selected radio station collection
        ArrayList<String> selects = new ArrayList<String>();

        //Define a temporary set to store the intersection of the area covered by the radio station during the traversal and the area not covered at present
        HashSet<String> tempSet = new HashSet<String>();

        //Define a maxTemp to store the number of uncovered regions of the maximum tempSet
        int maxTemp;

        //Defined to maxKey and saved in one traversal process, the key of the radio station corresponding to the largest uncovered area can be covered
        //If the maxKey is not null, it will be added to the selections
        String maxKey = null;
        while(allAreas.size() != 0) { // If allAreas is not 0, it means that all regions have not been covered
            //For each while, you need to
            maxKey = null;
            maxTemp = 0;
            //Traverse broadcasts and get the corresponding key
            for(String key : broadcasts.keySet()) {
                //Every time
                //The area that this key can cover at present
                HashSet<String> areas = broadcasts.get(key);
                //Find the intersection of tempSet and allAreas set, and the intersection will be assigned to tempSet
                //If the current collection contains more uncovered regions than the collection region pointed to by the maxKey
                //You need to reset the maxKey
                // Tempset. Size() > broadcasts. Get (maxkey). Size()) reflects the characteristics of greedy algorithm and selects the best one every time
                if(tempSet.size() > 0 &&
                        (maxKey == null || tempSet.size() > maxTemp)){
                    maxKey = key;
                    maxTemp = tempSet.size();
            //maxKey != null, you should add maxkey to selections
            if(maxKey != null) {
                //Remove the area covered by the radio station pointed to by maxKey from allAreas


        System.out.println("The selection result is" + selects);//[K1,K2,K3,K5]



5.4 precautions and details of greedy algorithm

1) The results obtained by greedy algorithm are not necessarily the optimal results (sometimes the optimal solution), but they are relatively approximate (close) to the optimal solution
2) For example, the algorithm in the above question selects K1, K2, K3 and K5, which covers all regions
3) However, we find that K2, K3, K4 and K5 can also cover all regions. If the use cost of K2 is lower than K1, K1, K2, K3 and K5 in the above question meet the conditions, but they are not optimal

Posted by anthony-needs-you on Fri, 24 Sep 2021 08:39:02 -0700