持续创作,加速成长!这是我参与「掘金日新计划 · 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.lengthn == grid[i].length1 <= n <= 500grid[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);
}
}
看时间应该算的上是最优解了
3.结束
9月18日每日一题打卡完毕,还是一个能自己做出来的困难题,加油!!!!!!!!gogogo,刷题刷题,每天一道,三年1000道!!!!