岛屿的最大面积(剑指Offer) -Java, Python实现


Problem: LCR 105. 岛屿的最大面积

思路

本题中说的是一个网格的岛屿,获取其中的岛屿的最大面积,是典型的图论的问题,可以采用广度优先搜索算法和深度优先算法,本文采用广度优先搜索算法

解题方法

① 定义已经访问过的岛屿的二维布尔数组
② 两层循环遍历网格,即第一层(最外层)循环是网格的行,第二层(最内层)循环是网格的列
③ 遍历到每个网格节点时,判断该节点时岛屿(其值是1),同时不是已经访问过的岛屿,则获取其岛屿的面积,并与最大的岛屿面积比较
④ 获取岛屿的面积的子函数 getArea(), 入参只要是 网格,是否已经访问过的二维数组,当前节点的横坐标,当前节点的纵坐标;返回值是整型的岛屿的面积
⑤ 获取岛屿面积的子函数中,定一个 岛屿节点Queue, Java语言中,就使用 LinkedList 实现就行,当前节点放入该队列,当前节点已访问,定义当前岛屿面积 area;
⑥ while循环岛屿节点队列,remove出当前岛屿节点,同时面积area增加1;for循环当前岛屿的前后左右四个节点,还是判断这四个节点的,纵横坐标是否在网格中,同时是否是岛屿,是否还没访问过,如果是的话,就放入到 岛屿节点队列中,这个节点被访问过

复杂度

  • 时间复杂度: 两层循环,时间复杂度: O(n2)O(n^2)
    O(n2)

  • 空间复杂度:空间复杂度: O(n)

Code

4.1)Java实现


class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int maxArea = 0;
        int row = grid.length;
        int col = grid[0].length;
        // 岛屿是否访问过的二维布尔数组
        boolean[][] visited = new boolean[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                // 节点是岛屿且没被访问过
                if (grid[i][j] == 1 && !visited[i][j]) {
                    int area = getArea(grid, visited, i, j);
                    maxArea = Math.max(area, maxArea);
                }
            }
        }

        return maxArea;
    }

    private int getArea(int[][] grid, boolean[][] visited, int i, int j) {
        // 岛屿节点队列
        Queue<int[]> queue = new LinkedList<>();
        int area = 0;
        queue.add(new int[]{i, j});
        visited[i][j] = true;

        // 岛屿的前后左右的四个方向
        int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

        // 广度优先搜索
        while (!queue.isEmpty()) {
            // 当前节点
            int[] pos = queue.remove();
            area++;
            for (int[] dir : dirs) {
                int r = pos[0] + dir[0];
                int c = pos[1] + dir[1];
                if (r >= 0 && r < grid.length
                    && c >= 0 && c < grid[0].length
                    && grid[r][c] == 1 && !visited[r][c]) {
                        queue.add(new int[]{r, c});
                        visited[r][c] = true;

                }
            }
        }
        return area;
    }
}

4.2)Python实现

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        maxArea = 0
        # 网格的行列
        row,col = len(grid), len(grid[0])  
        # 岛屿是否遍历过      
        visited = [[False for _ in range(col)] for _ in range(row)]
        for i in range(row):
            for j in range(col):
                # 是没有访问过的岛屿
                if grid[i][j] == 1 and not visited[i][j]:
                    area = self.getNowArea(grid, visited, i, j)
                    # 获取较大值
                    maxArea = max(maxArea, area)
        
        return maxArea


    def getNowArea(self, grid: List[List[int]], visited: List[List[bool]], i: int, j: int) -> int:
        area = 0
        # from Collections import dequeue
        queue = deque([(i, j)])
        # 当前节点被访问过
        visited[i][j] = True
        # 当前节点的前后左右4个方向
        dirs = [(-1,0), (1,0), (0,-1), (0,1)]

        # 广度优先算法
        while queue:
            pos = queue.popleft()            
            area += 1
            for dirItem in dirs:                
                row,col = pos[0] + dirItem[0], pos[1] + dirItem[1]
                # 在网格的边界访问里,同时是未被访问过的岛屿
                if 0 <= col < len(grid[0]) and 0 <= row < len(grid) and grid[row][col] == 1 and not visited[row][col]:
                    queue.append((row, col))
                    visited[row][col] = True

        return area




        

  1. python中的函数第1个参数要是 self
  2. 返回值的表现可以是 def yourFunction(self) -> int :
  3. Python中访问同一个类中的其他方法,可以是 self.otherfun()
  4. 不能自定义,但不初始化 python的变量,比如 本题中的是否被访问过的 二维布尔列表
    visited = [[False for _ in range(col)] for _ in range(row)]
  5. python中没有 三元判断符,使用 max()函数即可
    6) if判断语句不用使用小括号,“且”是 and, "或"是 or, 非是 not
  6. python中的队列是 deque() from Collections import deque
    左侧出队列是 queue.popleft() 返回值是 弹出来的元素
    8)布尔类型: bool
    真:True
    假: False
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值