Jiang Tiefu's brushing algorithm from zero (recursive backtracking--two-dimensional summary)

Posted by crseader on Sat, 20 Jun 2020 03:59:02 +0200

LeetCode 79, Word Search


First of all, we need to understand that each point can be used as a starting point in this topic. That is, we need a two-level loop to traverse each point and use this starting point to take its route to determine if the requirements of the topic can be met.
The general structure is actually consistent with one-dimensional recursive backtracking.
There are a few points to note:
1. In recursion, we need to go to the top, bottom, or left of the current point to make a judgement, so we can use an array

To optimize this process.

2. On the basis of optimization, it is necessary to determine whether the newly obtained actual point is in a two-dimensional plane.

3. In a search that starts at the beginning point, all points cannot be judged repeatedly, so a two-dimensional Boolean array corresponding to board is defined to record whether the point has been judged in the current search.
This value needs to be set to the initial value in the backtrace process.
4. Recursive end condition. When the last point is judged, if the point is judged successfully, it can be found.Otherwise not.

Here's all the code:

class Solution {
    int[][] move={{0,-1},{-1,0},{0,1},{1,0}};
    boolean[][] ismoved;
    public boolean exist(char[][] board, String word) {
        if((board.length*board[0].length)<word.length()||board.length==0||word.length()==0){
            return false;
        }
        ismoved=new boolean[board.length][board[0].length];
    
        for(int i=0;i<board.length;i++){
            for(int j =0;j<board[i].length;j++){
                if(searchword(board,word,i,j,0)){
                    return true;
                }
            }
        }
        return false;
    }

    public boolean searchword(char[][] board,String word,int satrtx,int starty,int index){
        if(index==word.length()-1){
            if(word.charAt(index)==board[satrtx][starty]){
                return true;
            }
            return false;
        }
        if(word.charAt(index)==board[satrtx][starty]){
            ismoved[satrtx][starty]=true;
            for(int i =0;i<4;i++){
                int newx =satrtx+move[i][0];
                int newy =starty+move[i][1];
                if(isValid(newx,newy,board)&&!ismoved[newx][newy]){
                    if(searchword(board,word,newx,newy,index+1))
                    return  true;
                }
            }
            ismoved[satrtx][starty]=false;
        }
    return false;
    }
    public boolean isValid(int satrtx,int starty,char[][] board){
        if(satrtx>=0&&satrtx<board.length&&starty>=0&&starty<board[0].length){
            return true;
        }
        return false;
    }
}

LeetCode 200, number of islands


It's still a two-dimensional recursive backtrace, which is also called the floodfill problem.
Similar to the above question, we only need to set the point equal to'1'as the starting point, start the search, set the point equal to 1 to the point already found in the recursive process.So when we set the starting point, we need to set it equal to'1', and it's not traversed.
There is no need to set an end condition on a recursive function because it only needs to recurse all the points, hide the condition in whether it is equal to'1', whether it has been traversed, and whether it is a valid point.
Add one to the number at the start of each valid operation.

class Solution {
    boolean[][] isvalid;
    int[][] move ={{-1,0},{0,-1},{1,0},{0,1}};
    int m,n;
    int sum=0;
    public int numIslands(char[][] grid) {
        m=grid.length;
        if(m==0) return 0;
        n=grid[0].length;
        isvalid=new boolean[m][n];
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='1'&&!isvalid[i][j]){
                    isvalid[i][j]=true; 
                    sum++;
                    floodfill(grid,i,j);
                }
            }
        }
        return sum;
    }
    public void floodfill(char[][] grid,int startx,int starty){
   
            for(int i=0;i<4;i++){
                int newx =startx+move[i][0];
                int newy =starty+move[i][1];
                if(ismoved(newx,newy)&&!isvalid[newx][newy]&&grid[newx][newy]=='1'){
                    isvalid[newx][newy]=true;
                    floodfill(grid,newx,newy);
                }
            }
    }

    public boolean ismoved(int startx,int starty){
        if(startx>=0&&startx<m&&starty>=0&&starty<n){
            return true;
        }
        return false;
    }
}

LeetCode 130, Surrounded Area


It's still a framework, but what I'm going to say here should be a rather clumsy approach.
This is actually very similar to the question above.
I use the method that says'X'must surround'O', so I start looking for'O' from the boundary and set it to true whether it traverses or not.Then, from the boundary, another recursive method with the change value is executed, since the unsatisfied O is found and set as true for the first time.I won't look again next time.

class Solution {
     boolean[][] isvalid;
    int[][] move ={{-1,0},{0,-1},{1,0},{0,1}};
    int m,n;
    public void solve(char[][] board) {
         m=board.length;
         if(board.length==0) return;
        n=board[0].length;
        isvalid=new boolean[m][n];
        for(int i=1;i<m-1;i++){
            if(board[i][0]=='O'&&!isvalid[i][0]){
                    isvalid[i][0]=true;   
                    floodfill(board,i,0);
                }
        }
        for(int i=1;i<m-1;i++){
            if(board[i][n-1]=='O'&&!isvalid[i][n-1]){
                    isvalid[i][n-1]=true;   
                    floodfill(board,i,n-1);
                }
        }
         
        for(int j=0;j<n;j++){
            if(board[0][j]=='O'&&!isvalid[0][j]){
                    isvalid[0][j]=true;   
                    floodfill(board,0,j);
            }
        }
        for(int j=0;j<n;j++){
            if(board[m-1][j]=='O'&&!isvalid[m-1][j]){
                    isvalid[m-1][j]=true;   
                    floodfill(board,m-1,j);
            }
        }
                
        for(int i=1;i<m-1;i++){
            for(int j=1;j<n-1;j++){
                if(board[i][j]=='O'&&!isvalid[i][j]){
                    isvalid[i][j]=true;
                    board[i][j]='X'; 
                    floodfill1(board,i,j);
                }
            }
        }
    }
 public void floodfill(char[][] grid,int startx,int starty){
   
            for(int i=0;i<4;i++){
                int newx =startx+move[i][0];
                int newy =starty+move[i][1];
                if(ismoved(newx,newy)&&!isvalid[newx][newy]&&grid[newx][newy]=='O'){        
                    isvalid[newx][newy]=true;
                   
                    floodfill(grid,newx,newy);
                }
            }
    }
     public void floodfill1(char[][] grid,int startx,int starty){
   
            for(int i=0;i<4;i++){
                int newx =startx+move[i][0];
                int newy =starty+move[i][1];
                if(ismoved(newx,newy)&&!isvalid[newx][newy]&&grid[newx][newy]=='O'){        
                    isvalid[newx][newy]=true;
                     grid[newx][newy]='X';
                    floodfill1(grid,newx,newy);
                }
            }
    }

    public boolean ismoved(int startx,int starty){
        if(startx>=0&&startx<m&&starty>=0&&starty<n){
            return true;
        }
        return false;
    }
   
}

LeetCode 417, Pacific Atlantic Current Issues



My method is still foolish.
I want to optimize it, but I don't want it to fail. I want the big guys I see to help me.
The general process is the same as above, noting that the new point is equal to or less than the value of the previous point.
The main idea of my foolproof approach is that a point must be able to reach both the Pacific and the Atlantic Oceans, so use two recursive functions to determine whether it can reach both the Pacific and the Atlantic Oceans.If all are true, the point is stored in the res.

class Solution {
    int m,n;
    boolean[][] falgs ;//Judging whether to walk
    boolean[][] isvalidp;//Save every point to the Pacific Ocean
    boolean[][] isvalida;//Find out if each point can reach the Atlantic Ocean
    boolean[][] novalidp;//Points that must not reach the Pacific Ocean
    boolean[][] novalida;//It must not reach the Atlantic Ocean

    int[][] move={{-1,0},{1,0},{0,-1},{0,1}};
    List<List<Integer>> res =new ArrayList<>();
    public  List<List<Integer>> pacificAtlantic(int[][] matrix) {
         m = matrix.length;
        if(m==0) return res;
         n =matrix[0].length;
        falgs =new boolean[m][n];
        isvalidp =new boolean[m][n];
        isvalida=new boolean[m][n];
        novalidp=new boolean[m][n];
        novalida=new boolean[m][n];


         List<Integer> list1;
        for(int i=0;i<m;i++){
            for(int j =0;j<n;j++){
                falgs[i][j]=true;
                List<Integer> list =new ArrayList<>();
                if(gogogop(matrix,i,j,m,n)&&gogogoa(matrix,i,j,m,n)){
                    list.add(i);
                    list.add(j);
                    list1 =new ArrayList<>();
                     list1.addAll(list);
                    res.add(list1);
                    isvalidp[i][j]=true;
                    isvalida[i][j]=true;
                }
                falgs[i][j]=false;
            }
        }
        return res;
    }
    public boolean gogogop(int[][] matrix,int startx,int starty,int m,int n){
        if(startx==0||starty==0) return true;
        if(isvalidp[startx][starty]) return true;
        //if(novalidp[startx][starty]) return false;
        for(int i =0;i<4;i++){
            
            int newx =startx+move[i][0];
            int newy =starty+move[i][1];
            
            if(isvalided(newx,newy)&&!falgs[newx][newy]&&matrix[newx][newy]<=matrix[startx][starty]){       falgs[newx][newy]=true;
                 if(gogogop(matrix,newx,newy,m,n)){
                 falgs[newx][newy]=false;
                 isvalidp[newx][newy]=true;
                     return true;
                 }
                 falgs[newx][newy]=false;
                 
            }
            
        }
        //novalidp[startx][starty]=true;
        return false;
    } 
     public boolean gogogoa(int[][] matrix,int startx,int starty,int m,int n){
        if(startx==m-1||starty==n-1) return true;
        if(isvalida[startx][starty]) return true;
       // if(novalida[startx][starty]) return false;
        for(int i =0;i<4;i++){

            int newx =startx+move[i][0];
            int newy =starty+move[i][1];
            
            if(isvalided(newx,newy)&&!falgs[newx][newy]&&matrix[newx][newy]<=matrix[startx][starty]){       falgs[newx][newy]=true;
                 if(gogogoa(matrix,newx,newy,m,n)){ 
                     falgs[newx][newy]=false;
                     isvalida[newx][newy]=true;
                     return true;
                 }
                 falgs[newx][newy]=false;
            }
            
        }
        //novalida[startx][starty]=true;
        return false;
    } 
     public boolean isvalided(int startx,int starty){
        if(startx>=0&&startx<m&&starty>=0&&starty<n){
            return true;
        }
        return false;
    }
}

Just write that much first.Keep on learning.
Go China.

Topics: less