[杨小白]_leetcode_827. 最大人工岛

60 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

这是9月18日每日一题

827. 最大人工岛

给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。

返回执行此操作后,grid 中最大的岛屿面积是多少?

岛屿 由一组上、下、左、右四个方向相连的 1 形成。

示例 1

  • 输入: grid = [[1, 0], [0, 1]]
  • 输出: 3
  • 解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。

示例 2

  • 输入: grid = [[1, 1], [1, 0]]
  • 输出: 4
  • 解释: 将一格0变成1,岛屿的面积扩大为 4。

示例 3

  • 输入: grid = [[1, 1], [1, 1]]
  • 输出: 4
  • 解释: 没有0可以让我们变成1,面积依然为 4。

提示:

  • n == grid.length
  • n == grid[i].length
  • 1 <= n <= 500
  • grid[i][j] 为 0 或 1

2.解析

做法其实比较简单,首先new了一个num数组,用来记录i,j点是否遍历过了。然后就开始遍历整个grid,每到一个陆地,就用dsf函数,把整个陆地都标记上序号index,每标记一次index就加一。

index相同的岛屿是连通着的,是同一块岛屿。

现在再新建一个输出gridarea,长度为index-1,顾名思义,这个数组记录了编号为i的岛屿的面积。

第二次遍历整个岛屿,更新gridarea。

第三次遍历整个岛屿,如果是陆地,则跳过,如果是水域,那么就使用一个hashset将这个水域的上下左右四块岛屿的序号存下来(如果存在上下左右,并且是陆地的话)

为什么用hashset呢,然后一个水域的上方和下方都是1号岛屿,实际上我们只能算一个gridarea[1],而不能加两次。

每次更新res返回即可。

class Solution {
    int[][] num;

    public int largestIsland(int[][] grid) {
        num = new int[grid.length][grid[0].length];
        int index = 1;
        for (int i = 0; i < grid.length; i++) {  //第一次遍历,dfs,遍历完后,num中水域为-1,每块岛屿的值都是自己的序号,且都不相同。
                                                //比如有4块岛屿,此时index为5,每块岛屿的值分别是1,2,3,4
                                                //例[[1,0,1],[1,1,0],[0,0,1]] 遍历完后为[[1,0,2],[1,1,0],[0,0,3]]
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 0) {
                    num[i][j] = -1;
                }
                if (num[i][j] == 0) {
                    dsf(i, j, index, grid);
                    index++;
                }
            }
        }
        int[] gridarea = new int[index - 1]; //统计编号为n的岛屿的面积为gridarea[n-1]
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (num[i][j] != -1) {
                    gridarea[num[i][j] - 1]++;
                }
            }
        }
        int res = 0;
        for (int i = 0; i < gridarea.length; i++) {  //res初始值是最大的岛屿面积[[1,1],[1,1]]是res为4
            res = Math.max(res, gridarea[i]);
        }
        for (int i = 0; i < grid.length; i++) {  //fun函数计算将i,j水域填为陆地后,连同起来的四块地所属岛屿面积相加
            for (int j = 0; j < grid[0].length; j++) {
                if (num[i][j] == -1) {
                    res = Math.max(res, fun(i, j, gridarea) + 1);
                }
            }
        }
        return res;
    }

    public int fun(int i, int j,int[] gridarea) {
        HashSet<Integer> set = new HashSet<>();
        if (i > 0 && num[i - 1][j] != -1) set.add(num[i - 1][j]);
        if (j > 0 && num[i][j - 1] != -1) set.add(num[i][j - 1]);
        if (i < num.length - 1 && num[i + 1][j] != -1) set.add(num[i + 1][j]);
        if (j < num[0].length - 1 && num[i][j + 1] != -1) set.add(num[i][j + 1]);
        int res = 0;
        for (Integer a : set) {
            res = res + gridarea[a-1];
        }
        return res;
    }

    public void dsf(int i, int j, int index, int[][] grid) {
        if (num[i][j] != 0) return;
        if (grid[i][j] == 0) return;
        num[i][j] = index;
        if (i > 0) dsf(i - 1, j, index, grid);
        if (j > 0) dsf(i, j - 1, index, grid);
        if (i < grid.length - 1) dsf(i + 1, j, index, grid);
        if (j < grid[0].length - 1) dsf(i, j + 1, index, grid);
    }
}

image.png

看时间应该算的上是最优解了

3.结束

9月18日每日一题打卡完毕,还是一个能自己做出来的困难题,加油!!!!!!!!gogogo,刷题刷题,每天一道,三年1000道!!!!