问题:
难度:hard
说明:
给出一个二维数组,然后数组内元素只有 0 1,1代表陆地,0代表海,那么就将所有的 1 连成一片的区域作为岛屿,你允许使用一次填充处理,将一个 0 改为 1,然后再算出海域内填充后最大的一片岛屿是多少。
题目连接:https://leetcode.com/problems/making-a-large-island/
输入范围:
n == grid.length
n == grid[i].length
1 <= n <= 500
grid[i][j]
is either0
or1
.
输入案例:
Example 1:
Input: grid = [[1,0],[0,1]]
Output: 3
Explanation: Change one 0 to 1 and connect two 1s, then we get an island with area = 3.
Example 2:
Input: grid = [[1,1],[1,0]]
Output: 4
Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4.
Example 3:
Input: grid = [[1,1],[1,1]]
Output: 4
Explanation: Can't change any 0 to 1, only one island with area = 4.
我的代码:
首先是求岛屿面积,这个就很简单,直接一个dfs就行,如果加多一个条件,可以填充,那么我可以先算出所有的岛屿面积,然后最后逐个找到可填充的地,然后再填充看看面积如何就行了。
class Solution {
private int max = Integer.MIN_VALUE, index = 0;
private List<Integer> cache = new ArrayList<Integer>();
public int largestIsland(int[][] grid) {
if(grid.length == 0 || grid[0].length == 0) return 0;
int x = grid.length, y = grid[0].length;
int[][] board = new int[x][y];
for(int i = 0; i < x; i ++) Arrays.fill(board[i], -1);
boolean[][] visited = new boolean[x][y];
for(int i = 0; i < x; i ++) // 先计算所有面积
for(int j = 0; j < y; j ++)
if(!visited[i][j] && grid[i][j] == 1) {
int tmp = count(grid, i, j, visited, 0, grid.length, grid[0].length, board);
max = Math.max(max, tmp);
cache.add(tmp);
index ++;
visited[i][j] = true;
}
for(int i = 0; i < x; i ++) // 再逐个填充查看面积
for(int j = 0; j < y; j ++)
if(!visited[i][j]) {
max = Math.max(max, search(i, j, grid, board));
visited[i][j] = true;
}
return max;
}
public int search(int i, int j, int[][] grid, int[][] board) {
int val = 1, idx = -1;
int arr[] = new int[4];
Arrays.fill(arr, -1);
if(isValid2(grid, i + 1, j, grid.length, grid[0].length, board, arr)) {
val += cache.get(board[i + 1][j]);
arr[++ idx] = board[i + 1][j];
}
if(isValid2(grid, i - 1, j, grid.length, grid[0].length, board, arr)) {
val += cache.get(board[i - 1][j]);
arr[++ idx] = board[i - 1][j];
}
if(isValid2(grid, i, j + 1, grid.length, grid[0].length, board, arr)) {
val += cache.get(board[i][j + 1]);
arr[++ idx] = board[i][j + 1];
}
if(isValid2(grid, i, j - 1, grid.length, grid[0].length, board, arr)) {
val += cache.get(board[i][j - 1]);
arr[++ idx] = board[i][j - 1];
}
return val;
}
public int count(int[][] grid, int x, int y, boolean[][] visited, int val, int xlen, int ylen, int[][] board) {
val ++;
board[x][y] = index;
visited[x][y] = true;
val = count2(grid, x + 1, y, visited, val, xlen, ylen, board);
val = count2(grid, x - 1, y, visited, val, xlen, ylen, board);
val = count2(grid, x, y + 1, visited, val, xlen, ylen, board);
val = count2(grid, x, y - 1, visited, val, xlen, ylen, board);
return val;
}
public int count2(int[][] grid, int x, int y, boolean[][] visited, int val, int xlen, int ylen, int[][] board) {
if(isValid(grid, x, y, visited, xlen, ylen))
val = count(grid, x, y, visited, val, xlen, ylen, board);
return val;
}
public boolean isValid(int[][] grid, int x, int y, boolean[][] visited, int xlen, int ylen) {
return x >= 0 && x < xlen
&& y >= 0 && y < ylen
&& !visited[x][y]
&& grid[x][y] == 1;
}
public boolean isValid2(int[][] grid, int x, int y, int xlen, int ylen, int[][] board, int[] arr) {
if(x >= 0 && x < xlen
&& y >= 0 && y < ylen
&& grid[x][y] == 1) {
int tmp = board[x][y];
for(int i = 0; i < 4; i ++)
if(arr[i] == tmp) return false;
return true;
}
return false;
}
}