力扣经典深度优先+递归算法

Posted 牛牛最爱喝兽奶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣经典深度优先+递归算法相关的知识,希望对你有一定的参考价值。

深度优先算法

1.有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-closed-islands

代码

class Solution 
    int[][] dir = new int[][]//定义四个方向
        1,0,-1,0,0,-1,0,1
    ;
    boolean[][] visited;//用于判断是否走过
    public int closedIsland(int[][] grid) 
        int row = grid.length;//获取行数
        int col = grid[0].length;//获取列数
        visited=new boolean[row][col];//初始化数组
        int count=0;//定义封闭岛数
        for(int i=0;i<row;i++)//循环遍历每一个位子
            for(int j=0;j<col;j++)
                if(!visited[i][j]&&grid[i][j]==0)//如果当前位置没有走过,且当前位置是岛屿
                    if(dfsFindLand(grid,col,row,i,j))//递归判断当前是不是封闭岛屿
                    count++;//是的话++
                
            
        
        return count;//最终返回结果
    
    public boolean dfsFindLand(int[][] grid,int col,int row,int curRow,int curCol)//深度优先算法
       if(curCol>=col||curCol<0) return false;//越界处理
       if(curRow>=row||curRow<0)  return false;//越界处理
       if(grid[curRow][curCol]==1||visited[curRow][curCol]) return true;//当前位置是海,或者已经走过,返回true
       visited[curRow][curCol]=true;//设置当前位置已经访问过
       boolean flag = true;//定义一个标记
       for(int arr[]:dir)//循环走四个方向,
           if(!dfsFindLand(grid,col,row,curRow+arr[0],curCol+arr[1]))
                    flag =false;//当前位置不是一个闭环岛屿
       
       return flag;
    

2.给定一个包含了一些 0 和 1 的非空二维数组 grid 。
一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-area-of-island

代码:

class Solution 
    int row,col;//定义全局变量行和列
    int cnt ;//当前的岛屿面积
    public int maxAreaOfIsland(int[][] grid) 
        row = grid.length;//获取行
        col = grid[0].length;//获取列
        int res=0;//初始话,记录最大岛屿面积
        for(int i=0;i<row;i++)//循环遍历。。。
            for(int j=0;j<col;j++)
                if(grid[i][j]==1)
                    cnt=dfs(grid,i,j);//记录当前位置出发形成的岛屿数
                     if(cnt>res)//取最大值
                         res=cnt;
                     
                
            
        
        return res;
    
    public int dfs(int[][] grid,int x,int y)//同样采用深度优先算法
        int count=1;//初始化
        if(x>=row||x<0||y>=col||y<0||grid[x][y]==0)//越界或当前是海洋
            return 0;
        
        grid[x][y]=0;//表示当前位置已经计算了,将其设置为海
        count+=dfs(grid,x+1,y);//每个方向去访问,并记录岛屿数
        count+=dfs(grid,x-1,y);
       count+= dfs(grid,x,y-1);
        count+=dfs(grid,x,y+1);
        return count;//最后返回总数
    

3.「以扣会友」线下活动所在场地由若干主题空间与走廊组成,场地的地图记作由一维字符串型数组 grid,字符串中仅包含 “0"~"5” 这 6 个字符。地图上每一个字符代表面积为 1 的区域,其中 “0” 表示走廊,其他字符表示主题空间。相同且连续(连续指上、下、左、右四个方向连接)的字符组成同一个主题空间。
假如整个 grid 区域的外侧均为走廊。请问,不与走廊直接相邻的主题空间的最大面积是多少?如果不存在这样的空间请返回 0。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/YesdPw

代码:

class Solution 
//声明全局变量
    boolean[][] vis;//设置是否访问
    boolean adjoin;//记录当前是否为走廊
    int row,col;//行列
    int cnt;//记录最大的主题空间
    public int largestArea(String[] grid) 
         row = grid.length;//行
         col = grid[0].length();//列
        vis = new boolean[row][col];//初始化
        int res=0;//记录最大数的主题空间
        for(int i=0;i<row;i++)//循环遍历每个角标
            for(int j=0;j<col;j++)
                if(!vis[i][j])//没有访问过
                    adjoin=(grid[i].charAt(j)=='0');//当前是否为走廊
                    cnt=0;//初始值为0
                    dfs(grid,i,j,grid[i].charAt(j));//深度优先算法
                    if(!adjoin)//当前不是走廊
                        res = res>cnt?res:cnt;//去最大值
                    
                
            
        
    return res;//返回最大值
    
    public void dfs(String[] grid,int x,int y,char ch)//深度优先算法,这里加入一个char ch的目的是在于主题空间不唯一,只有相同的主题空间才能被组合
        if(x<0||y<0||x>=row||y>=col)//越界处理
            adjoin=true;
            return;
        
        char cur = grid[x].charAt(y);//获取当前位置的主题号
        if(cur!=ch||vis[x][y])//如果当前位置走过,或者当前主题数不相等,都会退出
            if(cur=='0')
                adjoin =true;
            
            return;
        
        vis[x][y] = true;//当前主题已经计算
        cnt++;//主题数加1
        dfs(grid,x+1,y,ch);//四个方向去寻找相同的主题,构成最大的主题空间
        dfs(grid,x,y+1,ch);
        dfs(grid,x-1,y,ch);
        dfs(grid,x,y-1,ch);
    

4.迷宫
这道题是自己加的,在学习过程中碰到过类似的题目!

public class Maze 
private static LinkedList<String> stack = new LinkedList<>();//双向循环链表,既可以是栈结构也可以是队列
private static int enterX = 1;//起点
private static int enterY = 0;
private static int exitX = 7;//终点
private static int exitY = 8;
private static boolean[][] visited = new boolean[9][9];//同样用于记录是否访问过
private static int direction[][] = -1, 0, 0, 1, 1, 0, 0, -1;//四个方向
private static int[][] maze = //迷宫二维数组,0表示路,1表示墙
1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 1, 0, 0, 0, 1, 1, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1,
1, 0, 0, 1, 0, 0, 1, 1, 1,
1, 1, 0, 1, 1, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 1, 0, 1,
1, 0, 1, 1, 1, 0, 0, 0, 1,
1, 1, 0, 0, 0, 0, 1, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1
;
public static void main(String[] args) 
go(enterX, enterY);//开始走迷宫,跟上???冲冲冲
for (String path : stack) //输出结果
System.out.println(path);


private static boolean go(int x, int y) //开始go!go!go!
stack.push("(" + x + "," + y + ")");//迈出了第一步 yes!
visited[x][y] = true;//标记当前走过
if (x == exitX && y == exitY) //你走出了迷宫yyds
return true;

for (int i = 0; i < direction.length; i++) //四个方向去走
int newX = x + direction[i][0];//行
int newY = y + direction[i][1];//列
if (isInArea(newX, newY) && isRoad(newX, newY) && !visited[newX][newY]) //如果当前是路,没有被走过,在范围之内(别跑偏了。。)
if (go(newX, newY)) //如果走得通继续走
return true;//返回true



stack.pop();//当前位置走不通记得弹栈,就是回去
return false;//返回走不通

private static boolean isRoad(int newX, int newY) //判断当前是否为路
return maze[newX][newY] == 0;

private static boolean isInArea(int newX, int newY) //越界了
return newX >= 0 && newX < 9 && newY >= 0 && newY < 9;

private static void print(int[][] board) //打印路
for (int i = 0; i < board.length; i++) 
for (int j = 0; j < board[i].length; j++) 
System.out.print(board[i][j] + " ");

System.out.println();


5.数独
再给老铁们加一个数独!!!

import java.util.Scanner;
/*
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
*/
public class Sudoku 
public static void main(String[] args) 
int[][] board = new int[9][9];
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < board.length; i++) //手动输入数独,0表示空位。。
//建议不要随便输入,因为有可能你输的数独无解
String line = scanner.nextLine();
for (int j = 0; j < line.length(); j++) 
board[i][j] = Integer.parseInt(line.charAt(j) + "");


solve(0, 0, board);//开始数独游戏

private static void solve(int row, int col, int[][] board) //row行 col列 board
if (row == 9) //当走到最后一行表示结束
print(board);//打印结果
 else 
if (board[row][col] == 0) //当前位置没有放任何数字
for (int以上是关于力扣经典深度优先+递归算法的主要内容,如果未能解决你的问题,请参考以下文章

岛屿的数量(深度优先搜索算法)

Python算法-深度优先搜索&广度优先搜索(DFS&BFS)

leetcode 695. Max Area of Island 岛屿的最大面积(中等)

leetcode-200 深度优先+广度优先 岛屿数量

LeetCode刷题之搜索(Java)

LeetCode刷题之搜索(Java)