zoukankan      html  css  js  c++  java
  • 岛屿的最大面积(力扣第695题)

    题目:

    给定一个包含了一些 0 和 1 的非空二维数组 grid 。

    一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

    找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

    示例:

    [[0,0,1,0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,1,1,0,1,0,0,0,0,0,0,0,0],
    [0,1,0,0,1,1,0,0,1,0,1,0,0],
    [0,1,0,0,1,1,0,0,1,1,1,0,0],
    [0,0,0,0,0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,0,0,0,0,0,0,1,1,0,0,0,0]]

    对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。

    分析:

      要求的是最大的岛屿面积,这个面积是按照组成岛屿的1的个数来计算的,而相邻的方向设置为水平和垂直。其实就是从某个值为1的点出发,从水平和垂直四个方向上向相邻的点行走,可以最多路过多少个值为1的点。那我么就可以利用深度优先遍历算法来解决:

      DFS的算法思想就是:从某一点出发,到达其某个邻接点后,再从这个邻接点出发,走向邻接点的邻接点,直到最终无路可走,然后再向上后退,走其他的邻接点,继续向下一直走,最终遍历完所有的点为止。

      那我们遍历这个二维数组,设置一个访问记录数组,记录数组中的点是否被访问,访问过的点就不能再访问了,每遍历到值为1的点时,它未被访问过,那么就从这个点出发,进行深度优先遍历,计算它能遍历的总的点的个数,再与当前最大值进行比较,如果比当前最大值大,那么就替换当前最大值,否则继续遍历数组中其他值为1的点。

      对于二维数组中的某一点(i,j),其可以走的方向有四个,可表示为:(1,0)、(-1,0)、(0,1)、(0,-1)

    代码:

        public int maxAreaOfIsland(int[][] grid) {
    
            if (grid == null){
                return 0;
            }
            int col = grid[0].length;
            int row = grid.length;
    
            boolean[][] isVisited = new boolean[row][col];
            int max_res = 0;
            for (int i = 0; i < row; i++) {
    
                for (int j = 0; j < col; j++) {
    
                    if (!isVisited[i][j] && grid[i][j] == 1){
    
                        max_res = Math.max(max_res,curAreadByDFS(grid,i,j,isVisited));
                    }
                }
            }
            return max_res;
        }
    
        private int curAreadByDFS(int[][] grid,int r,int c,boolean[][] isVisited){
    
            int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
            Stack<Pair<Integer, Integer>> stack = new Stack<>();
            int length = 1;
            stack.push(new Pair<>(r,c));
            isVisited[r][c] = true;
            while (!stack.isEmpty()){
                Pair<Integer, Integer> node = stack.peek();
                int currow = node.getKey();
                int curcol = node.getValue();
    
                int flag = 0;
                for (int[] dir : dirs) {
    
                    int nex_r = dir[0] + currow;
                    int nex_c = dir[1] + curcol;
                    if (nex_c < 0 || nex_r >= grid.length || nex_r < 0 || nex_c >= grid[0].length){
                        continue;
                    }
                    if (grid[nex_r][nex_c] == 1 && !isVisited[nex_r][nex_c]){
                        stack.push(new Pair<>(nex_r,nex_c));
                        isVisited[nex_r][nex_c] = true;
                        length++;
                        flag = 1;
                        break;
                    }
                }
                if (flag == 0){
                    stack.pop();
                }
            }
    
            return length;
        }

      我采用的DFS算法是通过非递归的形式实现的,借助于栈,实现DFS。设置变量flag的原因是为了通知何时可以将当前访问的顶点压出栈,我们遍历当前顶点的相邻点的时候,是从当前顶点的四个相邻位置遍历的,四个方向遍历完毕时,如果未找到当前顶点可以继续向下走的顶点,那么说明此时这个顶点已经无路可走,那么它也就没有必要再留到栈里面,而是向上返回到当前顶点的前一步顶点,遍历其前一步顶点是否有路可走。

      如果通过判断方向选择遍历完毕来说明要压出栈,是会出问题的,因为退出方向遍历的for循环只有两种可能:一是找到了邻接点,二是遍历完成了;但是这两种可能有耦合到一起的可能,也就是在最后一个方向的时候,找到了邻接点,那么此时就不能将栈顶元素压出。

  • 相关阅读:
    数组与集合互转
    复选框 查看详情
    SQL Server 查询表备注信息的语句
    MSSql Server 索引'uq_f_userName' 依赖于 列'f_userName'。由于一个或多个对象访问此列,ALTER TABLE ALTER COLUMN f_userName 失败
    玄鸟
    Window Server 2012 R2 下 IE11 浏览器 无法安装Flash 怎么解决
    Window Server 2012 R2 没有照片查看器 打开图片都是画板问题怎么解决
    君子偕老
    燕燕
    羔羊
  • 原文地址:https://www.cnblogs.com/yxym2016/p/13155131.html
Copyright © 2011-2022 走看看