bfs --广度优先遍历/深度优先遍历

在程序考虑bfs算法的时候,需要考虑两个问题:

1、标记: 对于遍历过的节点,应该将它标记,防止重复遍历

2、需要一个队列来存储每一轮遍历得到的节点

深度优先遍历: 

class Solution {
     private  int[][] directions = {{-1,0},{0,1},{1,0},{0,-1}} ;  // 定义方向数组,分别表示上右下左 横向第一个参数是0,纵向第二个参数是0

    private int row,col; //定义总的行数和列数

    public int maxAreaOfIsland(int[][] grid){
            if(grid==null || grid.length==0) return 0;

            row = grid.length;
            col = grid[0].length;

            int maxArea = 0;

            for(int i =0;i<row;i++){
                for (int j =0;j<col;j++){
                    maxArea = Math.max(maxArea,dfs(grid,i,j));
                }
            }

       return  maxArea;
    }

    // dfs深度优先遍历

    private int dfs(int[][] grid,int r ,int c){

        // 判断当前传入坐标是否越界或者是水域
        if(r<0 || r>=row ||c<0 ||c>=col || grid[r][c] ==0){
            return 0; //满足任意一种情况就说明不是岛屿或者不在图内
        }


        grid[r][c] =0; //已经访问过的岛屿也修改为0,避免重复访问
        int area =1 ; // 每个岛屿的面积都是1,固定大小的

        for(int[] d :directions){
            //在四个方向上进行深度优先探寻,探寻完毕再访问上一层累加     d[0] 横坐标

            area += dfs(grid,r+d[0],c+d[1]);
        }
        return area;
    }
}

 

class Solution {
     private int[][] directions ={{-1,0},{0,1},{1,0},{0,-1}};
     private int m,n;
    
    public int numIslands(char[][] grid) {
        m=grid.length;
        n=grid[0].length;

        int areaCount =0;

        for(int i=0;i<m;i++){
            for (int j =0;j<n;++j)
            {   //是岛屿就进行深度优先遍历
                if(grid[i][j] == '1'){ 
                    dfs(grid,i,j);
                    areaCount++; //数量+1
                }
            }
        }
        return areaCount;
    }

    private void dfs(char[][] grid ,int i,int j){ //并不需要返回值,因为只是用来遍历

        if(i<0 || i>=m || j<0 || j>=n || grid[i][j] != '1'){ 
            //越界或者是水域的时候不进行dfs操作
            return ;
        }

        grid[i][j] ='0'; //表示这个岛屿访问过了

        for(int[] d :directions){ //进行深度优先遍历
            dfs(grid,i+d[0],j+d[1]);
        }
    }

 
}

class Solution {
   
    // 就是寻找在非对称轴上1的个数,且这个矩阵关于主轴对称,只需要看一半 因为(i,j)=1 与(j,i) = 1是一个意思

    // 矩阵是一个方阵

    public int findCircleNum(int[][] isConnected) {
       int n= isConnected.length;

       // 访问过的城市无需再次访问 true访问过,false没有访问
        boolean[] visited = new boolean[n];

        int provices=0;

        for(int i =0;i<n;i++){

            //如果当前城市i没有访问过,就去执行dfs,找到所有和i相连的城市

            if(!visited[i]){
                dfs(isConnected,i,visited);

                // 一趟dfs结束后,所有与i相连的城市都找到
                provices++;
            }

        }
        return provices;
    }

    private void dfs(int[][] isConnected,int i,boolean[] visited){

        visited[i]=true; //初始访问标记为true 
        
        for(int j=0;j<isConnected.length;j++){
            // 如果城市i和城市j相连,并且城市j还未访问过,就以j为新的节点继续递归找到与j相连的其他城市
            if(isConnected[i][j]==1 && !visited[j]){
                dfs(isConnected,j,visited);
            }
        }

    }

}

 

 

class Solution {

    /**
        思路:先用dfs,把所有四边边缘上的o以及与其相连的里面的o改成T,剩下的就是里面被x包围
        的o,
     */

     private int[][] directions = {{-1,0},{0,1},{1,0},{0,-1}};
     private int row,col;

    public void solve(char[][] board) {
        row = board.length;
        col = board[0].length;

        // 首先按行进行dfs,把图的左边缘与右边缘上所有的o以及与其相连的o全部改成T;
        for(int i=0;i<row;i++){
            dfs(board,i,0);
            dfs(board,i,col-1);
        }

        // 上下的边缘
        for(int j =0;j<col;j++){
            dfs(board,0,j);
            dfs(board,row-1,j);
        }

        // 最后遍历一遍图把所有的T恢复成o,把所有的o改成x
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(board[i][j]=='T'){ // 换回去
                    board[i][j]='O';
                }else if(board[i][j]=='O'){  // 按题目要求改成o
                    board[i][j]='X';
                }
            }
        }

    }

    

    //深度优先遍历
    private void dfs(char[][] board,int r,int c){
        // 判断是否越界
        if(r<0 || r>=row || c<0|| c>=col || board[r][c] !='O'){return;}

        board[r][c] ='T'; // 四周边缘上的变成T

        for(int[] d:directions){
            dfs(board,r+d[0],c+d[1]);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zero _s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值