Algorithm from getting started to giving up -- the fourth issue

Posted by cal_biker on Tue, 23 Nov 2021 04:55:25 +0100

Recently, we have been reading the classic series carefully. The main reason is that we have brushed a lot of algorithm problems. In order to keep up with the update rhythm, we have supplemented the algorithm from getting started to giving up the series.

Most of the previous string splits are dynamic rules. Today we do some DFS, which is not supported by popular science. Let's go directly to the topic.

A little conclusion before the question: DFS can have a return value, and DFS must be built according to our requirements. The process of the algorithm can have templates, but the details of the algorithm must be based on the requirements. If the requirements are sum here, int will be returned. If the requirements are to change the state in DFS, void will be returned. In short, the return value of DFS must be based on the requirements. Don't memorize it by rote, I think DFS has no return value.

The most common common DFS is tree DFS, which is relatively simple in the algorithm. When it rises to the graph (of course, the tree is also a graph), the more basic problem is the island problem.

Island questions are also from easy to difficult, but they are inseparable from the first foundation. Let's start with two foundations

1. Path in matrix

Given a   m x n 2D character grid   board and a string word   word . If   If word exists in the grid, return true; Otherwise, false is returned.

Words must be formed alphabetically by letters in adjacent cells, where "adjacent" cells are those horizontally or vertically adjacent. Letters in the same cell cannot be reused.

For example, in 3 below × The matrix of 4 contains the word "ABCCED" (the letters in the word are marked).

Example 1:

Input: board = ["a", "B", "C", "e"], ["s", "F", "C", "s"], ["a", "d", "e", "e"]], word = "abcced"
Output: true
Example 2:

Input: board = ["a", "B"], ["C", "d"]], word = "ABCD"
Output: false

The traversal of a graph must be in all directions, which can be inferred from the DFS of the tree. The tree has DFS of the left and right subtrees. If it is the adjacency matrix of a graph, it traverses in four directions. The idea should be different. There is a template for the specific implementation:

    public static boolean existsss(char[][] board, String word) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (dfsexist(board, i, j, word, 0)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean dfsexist(char[][] board, int i, int j, String word, int index) {
        if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || word.charAt(index) != board[i][j] || index > word.length() - 1) {
            return false;
        }
        if (index == word.length() - 1) {
            return true;
        }
        char temp = board[i][j];
        board[i][j] = '*';
        boolean res = dfsexist(board, i - 1, j, word, index + 1)
                || dfsexist(board, i, j - 1, word, index + 1)
                || dfsexist(board, i + 1, j, word, index + 1)
                || dfsexist(board, i, j + 1, word, index + 1);
        board[i][j] = temp;
        return res;
    }

  It should be noted here that the return value of dfs should be determined according to the needs. The purpose of dfs here is to see whether I want to go up, down, left and right or not when I am standing under the [i][j] grid. Therefore, I return true/false. Don't take it for granted here. It should not be difficult to understand

2. Number of islands

Give you a chance  ' A two-dimensional grid composed of 1 '(land) and 0' (water). Please calculate the number of islands in the grid.

Islands are always surrounded by water, and each island can only be formed by adjacent land connections in the horizontal and / or vertical direction.

In addition, you can assume that all four sides of the mesh are surrounded by water.

Example 1:

Input: grid =[
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
Output: 1
Example 2:

Input: grid =[
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
Output: 3

I'm still talking about setting the return of dfs as needed. I'm standing at [i][j] On the grid, as long as the grid is 1, it is an island or a part of the island. I walk in four directions. Whenever I encounter 1, it is still a part of the island, and the two parts accumulate an island, my task is to fill in the grid and stand at any point. If it is 0, skim over. If it is 1, fill all the points with 1 under my feet into 0,   It can't be filled in until the top, bottom, left and right. So, in fact, this dfs doesn't need to return a value. Just increase the total reference value count automatically when dfs exits. Therefore, the code is the above modification:

    public static int numIslands(char[][] grid) {
        int countIsLands = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if(grid[i][j]=='1'){
                    dfsIsLands(grid, i, j);
                    countIsLands++;
                }
            }
        }
        return countIsLands;
    }

    public static void dfsIsLands(char[][] grid, int i, int j) {
        if (i >= grid.length || i < 0 || j >= grid[0].length || j < 0 || grid[i][j] != '1') {
            return;
        }
        grid[i][j] = 0;
        dfsIsLands(grid, i, j - 1);
        dfsIsLands(grid, i + 1, j);
        dfsIsLands(grid, i - 1, j);
        dfsIsLands(grid, i, j + 1);
    }

(in the first edition, the life and death of static variables can't be used. I extremely doubt leetcode's misunderstanding of static variables( 🐕 First, from counting to crossword

3. Gold miner

You want to develop a gold mine. Geological surveyors have found out the distribution of resources in the gold mine and used the size of   The grid of m * n is marked. The integer in each cell represents the amount of gold in this cell; if the cell is empty, it is 0.

In order to maximize profits, miners need to mine gold according to the following rules:

Every time a miner enters a cell, all the gold in that cell is collected.
Miners can walk up, down, left and right from their current position at a time.
Each cell can only be mined (entered) once.
Do not mine (enter) cells with a gold number of 0.
Miners can start from any cell with gold in the grid or stop.
 

Example 1:

Input: grid = [[0,6,0],[5,8,7],[0,9,0]]
Output: 24
Explanation:
[[0,6,0],
 [5,8,7],
 [0,9,0]]
One route to collect the most gold is: 9 - > 8 - > 7.
Example 2:

Input: grid = [[1,0,7],[2,0,6],[3,4,5],[0,3,0],[9,0,20]]
Output: 28
Explanation:
[[1,0,7],
 [2,0,6],
 [3,4,5],
 [0,3,0],
 [9,0,20]]
One route to collect the most gold is: 1 - > 2 - > 3 - > 4 - > 5 - > 6 - > 7.

With the foreshadowing of the previous questions, I think the first feeling when you see this question should be: you can do it, but this question needs to do two things. The first thing is to come out and the second thing is to maximize. Coming out is obviously a backtracking. Try all the ways until you get the maximum. Each time you enter recursion, you can judge the following with the current maximum value.

   public int getMaximumGold(int[][] grid) {
        if (grid == null && grid.length == 0) {
            return 0;
        }
        int result = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                //The maximum value path that can be obtained from the current point of entry to the current point of exit and the current result result are whichever is greater
                result = Math.max(dfs(grid, i, j), result);
            }
        }
        return result;
    }

    public static int dfs(int[][] grid, int i, int j) {
        if (i >= grid.length || i < 0 || j >= grid[0].length || j < 0 || grid[i][j] == 0) {
            return 0;
        }
        int temp = grid[i][j];
        grid[i][j] = 0;
        int up = dfs(grid, i, j - 1);
        int right = dfs(grid, i + 1, j);
        int left = dfs(grid, i - 1, j);
        int down = dfs(grid, i, j + 1);
        int max = Math.max(up, Math.max(Math.max(right, left), down));
        grid[i][j] = temp;
        return grid[i][j] + max;
    }

4. Island Area

Given a   A non empty two-dimensional array of 0 and 1   grid  , A map used to represent Ocean Islands.

One   islands   By some adjacent   one   (representing land) composition. The "adjacent" here requires that two 1s must be adjacent horizontally or vertically. You can assume that   The four edges of the grid are surrounded by 0 (representing water).

Finds the largest island area in the given two-dimensional array. If there are no islands, the returned area is 0.

Example 1:

For a grid, it is a choice for a grid to be [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,, 1,1,0,0,0], [0,0,0,0,0,0,1,0,0,0,0,0]
Output: 6
Explanation: for the given matrix above, it should return   6. Note that the answer should not be 11, because the island can only contain 1 in four horizontal or vertical directions.

Back to the familiar crossword puzzle, just change 1 to 0 one by one. If you can't change it, write down how many have been changed. Just get the maximum, ez

    public int maxAreaOfIsland(int[][] grid) {
        if (grid == null && grid.length == 0) {
            return 0;
        }
        int mianjiResult = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                dfsMianji(grid, i, j);
                mianjiResult = Math.max(countResultMianji, mianjiResult);
                countResultMianji = 0;
            }
        }
        return mianjiResult;
    }
        static int countResultMianji = 0;
        public static void dfsMianji(int[][] grid, int i, int j) {
        if (i >= grid.length || i < 0 || j >= grid[0].length || j < 0 || grid[i][j] == 0) {
            return;
        }
        countResultMianji++;
        grid[i][j] = 0;
        dfsMianji(grid, i, j - 1);
        dfsMianji(grid, i + 1, j);
        dfsMianji(grid, i - 1, j);
        dfsMianji(grid, i, j + 1);
    }

  (you may see that my naming is awkward. Don't care about this detail. All my code is debugged in another java file. I have written thousands of lines of algorithm problems. Every time I write a new problem, I have to think about the name of methods and variables...)

That's all I've met for the time being. In fact, it's still very simple. It's not difficult to draw inferences from one instance. You need to bury your head in one stroke, and then you can eat your old capital. Come on!

Topics: Java Algorithm Back-end