Common basic algorithms

1. Sorting & Search Algorithm

1.1 Bubble sort

  • Compare adjacent data. Each iteration finds a maximum value.

  •     public void sort(int[] nums) {
          
          
            if (nums == null) {
          
          
                return;
            }
    
            for (int i = 0; i < nums.length; i++) {
          
          
                for (int j = 0; j < nums.length - 1 - i; j++) {
          
          
                    if (nums[j] > nums[j + 1]) {
          
          
                        int temp = nums[j];
                        nums[j] = nums[j + 1];
                        nums[j + 1] = temp;
                    }
                }
            }
        }
    

1.2 Binary search

1.3 Quick sort

  • There are several ways to write quick sort, including the left and right bilateral pointer exchange method and the unilateral pointer exchange method.

1.3.1 Left and right bilateral pointer exchange method

  1. Create two pointers on the left and right. Record the value of the left pointer as the boundary value, assuming it is the key.
  2. First, the right pointer finds the data coordinates smaller than the key from right to left , while ensuring that the left pointer is smaller than the right pointer.
  3. Then the left pointer finds the data coordinates larger than the key from left to right, while ensuring that the left pointer is smaller than the right pointer.
  4. The left and right pointers are exchanged and the next cycle is entered.
  5. The condition for ending a loop must be that the left and right pointers are equal. And the value pointed by the pointer at the end is less than or equal to key.
  6. After a loop ends, the data of the current pointer is exchanged with the boundary value.
  7. Then quickly sort the data on the left and right sides of the boundary respectively. (recursive)

1.3.2 leetcode

1.4 Bucket sorting

summary

insert image description here

2. Double pointers

3. Monotone stack

  • Push the numbers onto the stack at once, and at the same time require the elements in the stack to increase monotonically (or decrease). If the newly pushed number N is less than the number on the top of the stack, then pop it off the stack in sequence until the number N is greater than the element on the top of the stack.
  • Use the monotonic property as a critical point to solve the problem.
  • 503. The Next Greater Element II
  • 739. Daily temperature

4. Sliding window

  • Used to solve continuous subarray problems satisfying certain conditions

  • The sliding window cannot solve the problem of negative values. If there are negative values, you can consider using the prefix sum method to solve the problem.

  • 1208. Make strings equal as much as possible . In this question, the longest substring is the condition to be met, and it also meets the requirements of continuous subarrays.

5. Prefix sum

  • Used to solve continuous subarray problems that meet certain conditions.
  • Can solve problems with negative values ​​in the data.
  • Prefix and exploit properties: Sum(i...n) = Sum(n) - Sum(i). That is, the sum of consecutive subarrays from i to n is equal to Sum(n) - Sum(i).
  • #560 Subarray whose sum is K
  • #1124 Maximum period of good performance

六、DFS & BFS

  • Depth traversal is suitable for existential problems, and breadth traversal is suitable for finding the shortest path problem.
  • There are two ways to implement depth traversal: recursion and stack . Breadth traversal can only be implemented using queues .
  • When traversing, it is necessary to record the nodes that have been visited to avoid causing loops.
  • When traversing mazes, grids, and islands, consider traversing in four directions: up, down, left, and right. The direction array can be defined as follows to traverse the four directions:
private static final int[][] steps = {
    
    {
    
    1, 0}, {
    
    -1, 0}, {
    
    0, 1}, {
    
    0, -1}};

for (int[] step : steps) {
    
    
    Point next = new Point(point.x + step[0], point.y + step[1]);
    //省略...
}

6.1 Depth traversal

/**
 * grid 二维数组表示网格
 * current 表示当前正在遍历的节点
 * visited 表示已经遍历的节点,是set类型
 */
privte void dfs(int[][] grid, Point current, Set<Point> visited) {
    
    
    visited.add(current);
    for (int[] step : steps) {
    
     // 向四周遍历
        Point next = new Point(current.x + step[0], current.y + step[1]);
        if (visited.contains(next)) {
    
    
            continue;
        }

        // 不超出边界
        if (next.x >= 0 && next.x < grid.length && next.y >= 0 && next.y < grid[0].length) {
    
    
            if (grid[next.x][next.y] == 1) {
    
    
                number += dfs(grid, next, visited);
            }
            visited.add(next);
        }
    }
}

6.2 Breadth traversal

7. Backtracking algorithm

  • The backtracking algorithm is a derivative of depth-first algorithm and a traversal algorithm.
  • The backtracking algorithm can be used to solve the permutation problem, and there is a case of pruning

7.1 Classic question types

   // 数组全排列问题,回溯代码求解
    public List<List<Integer>> permute(int[] nums) {
    
    
        List<Integer> list = new ArrayList<>();
        for (int i : nums) {
    
    
            list.add(i);
        }

        List<List<Integer>> res = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();
        backtrack(list, temp, res);
        return res;
    }

    /**
     * 回溯方法
     *
     * @param list 原始数组
     * @param temp 一种排列结果
     * @param res 全排列结果合集
     */
    private void backtrack(List<Integer> list, List<Integer> temp, List<List<Integer>> res) {
    
    
        if (list.isEmpty()) {
    
    
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = 0; i < list.size(); i++) {
    
    
            temp.add(list.remove(i));
            backtrack(list, temp, res);
            list.add(i, temp.remove(temp.size() - 1));
        }
    }
    public List<List<Integer>> subsets(int[] nums) {
    
    
        List<Integer> list = new ArrayList<>();
        for (int i : nums) {
    
    
            list.add(i);
        }

        List<List<Integer>> result = new ArrayList<>();
        List<Integer> temp = new ArrayList<>();

        backtrack(list, result, temp, 0);
        return result;
    }

    private void backtrack(List<Integer> list, List<List<Integer>> result, List<Integer> tmp, int n) {
    
    
        result.add(new ArrayList<>(tmp));
        for (int i = n; i < list.size(); i++) {
    
    
            tmp.add(list.get(i));
            backTree(list, result, tmp, i +1);
            tmp.remove(tmp.size() - 1);
        }
    }

8. Dynamic programming

  • The key is to look for: state transition equations and boundary conditions , and then use recursion.
  • Because recursion may lead to repeated solutions, problems that have been solved should be recorded to avoid repeated operations.
  • Space optimization. Because when calculating F(n), only the values ​​​​of F(n - 1) and F(n - 2) are often needed, only these two values ​​​​can be retained during calculation to optimize the space complexity.

8.1 leetcode

9. Greedy Algorithm

10. Palindrome substring (horse-drawn cart algorithm)

  • Palindrome substrings are divided into odd symmetry and even symmetry. By inserting special characters, the string becomes evenly symmetrical.
  • Utilize the symmetry of palindromic substrings to improve traversal efficiency. When traversing, the characters on the right side of the known longest palindrome substring can directly use the traversal result of the characters at the left center symmetric position.
  • #5 The longest palindrome substring

11. Bit operations

Guess you like

Origin blog.csdn.net/followYouself/article/details/130676241