You are given row x col
grid
representing a map where grid[i][j] = 1
represents land and grid[i][j] = 0
represents water.
Grid cells are connected horizontally/vertically (not diagonally). The grid
is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells).
The island doesn't have "lakes", meaning the water inside isn't connected to the water around the island. One cell is a square with side length 1. The grid is rectangular, width and height don't exceed 100. Determine the perimeter of the island.
Example 1:
Input: grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]] Output: 16 Explanation: The perimeter is the 16 yellow stripes in the image above.
Example 2:
Input: grid = [[1]] Output: 4
Example 3:
Input: grid = [[1,0]] Output: 4
Constraints:
row == grid.length
col == grid[i].length
1 <= row, col <= 100
grid[i][j]
is0
or1
.- There is exactly one island in
grid
.
这道题看起来真的很dfs……然而不会写dfs就看了答案,然后发现其实根本用不上dfs……
1. 非dfs做法:直接计算有多少个1,有n个1就一共有4 * n条边。如果这个格子有左右/上下邻居,那就得-2。只要一直往一个方向看邻居,就不会重复计算。
Runtime: 6 ms, faster than 99.61% of Java online submissions for Island Perimeter.
Memory Usage: 42.5 MB, less than 99.82% of Java online submissions for Island Perimeter.
class Solution {
public int islandPerimeter(int[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
int result = 0;
int rows = grid.length;
int cols = grid[0].length;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == 1) {
result += 4;
if (j + 1 < cols && grid[i][j + 1] == 1) {
result -= 2;
}
if (i + 1 < rows && grid[i + 1][j] == 1) {
result -= 2;
}
}
}
}
return result;
}
}
2. dfs解法
DFS的解法看完了只能说妙啊。从任意一个land出发进行dfs,dfs递归函数里传入grid, visited(其实不传visited,直接改变grid的内容也行),和两个index。主要的难点在于终止条件的判断:如果递归到了边界以外、或者是个water,那就相当于从原来的格子往外试图扩张失败,就需要周长+1;如果递归到了visited了,那就啥也不干;如果还是land的话,就上下左右递归调用dfs函数进行扩散,并mark为visited。
reference:Loading...
Runtime: 21 ms, faster than 14.16% of Java online submissions for Island Perimeter.
Memory Usage: 62.1 MB, less than 62.58% of Java online submissions for Island Perimeter.
class Solution {
public int islandPerimeter(int[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
boolean[][] visited = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
return dfs(grid, visited, i, j);
}
}
}
return 0;
}
private int dfs(int[][] grid, boolean[][] visited, int i, int j) {
// if it's the boundary or water, return 1 as it has 1 edge that needs to be counted as perimeter
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) {
return 1;
}
// if it's already visited, don't count
if (visited[i][j]) {
return 0;
}
// if it's land, dfs to its neighbors
visited[i][j] = true;
return dfs(grid, visited, i - 1, j) + dfs(grid, visited, i + 1, j) + dfs(grid, visited, i, j - 1) + dfs(grid, visited, i, j + 1);
}
}