原题链接:
https://leetcode.cn/problems/island-perimeter/description/
完成情况:
解题思路:
解法一:
这段代码实现了计算岛屿的周长。通过遍历二维网格中的每个格子,检查其周围四个方向是否有水域或者边界,从而计算岛屿的周长。如果当前位置是陆地,并且从当前位置四个方向扩展的新位置是水域或者越界,则岛屿周长增加一条边。
解法二:
这段代码也实现了计算岛屿的周长。不同的是,它通过统计陆地数量和相邻陆地数量来计算周长,相邻的陆地会使总周长减少2。
解法三:延伸 - 傳統DFS解法:
这段代码采用了传统的深度优先搜索(DFS)方法,使用一个visited数组来记录已访问过的位置。在DFS过程中,遇到边界或者海水就增加周长。通过递归的方式遍历陆地区域,计算岛屿的周长。
该类中包含一个名为islandPerimeter
的函数,接受一个二维整数向量grid
作为参数,表示一个地图网格,其中1代表陆地,0代表水域。
代码中的变量sum
用于记录陆地的数量,cover
用于记录相邻陆地的数量。通过遍历整个地图网格,对每个陆地格子进行检查,如果是陆地,则增加sum
的计数,然后检查其上方和左侧是否也是陆地,如果是,则增加cover
的计数。这样做是为了避免重复计算相邻的陆地边界。
最后,函数返回的结果为(sum * 4 - cover * 2)
,即总周长等于陆地数量乘以4减去相邻陆地数量乘以2。这是因为每块陆地都贡献了4个边界,但相邻的两块陆地会共享2个边界,所以需要减去这部分重复计算的边界。
因此,这段代码的作用是计算给定地图网格中所有岛屿的总周长。
参考代码:
_463岛屿的周长_传统dfs
package 代码随想录.图论;
public class _463岛屿的周长_传统dfs {
//先定义出全局的position[][],visited[][]数组以及res返回值
int position[][] = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
boolean [][] visited;
int result = 0;
/**
*
* @param grid
* @return
*/
public int islandPerimeter(int[][] grid) {
int row = grid.length,column = grid[0].length;
visited = new boolean[row][column];
int result = 0;
for (int i = 0; i < row; i++) {
for (int j = 0;j < column;j++){
if (visited[i][j] == false && grid[i][j] == 1){
result += dfs_islandPerimeter(grid,i,j);
}
}
}
return result;
}
private int dfs_islandPerimeter(int[][] grid, int row, int col) {
//遇到边界的话,就是加1
//额外还需要判断一下grid[row][col] == 0,遇到下一个位置是海洋则直接跳过
if (row < 0 || col < 0 || row >= grid.length || col >= grid[0].length || grid[row][col] == 0){
return 1;
}
//不是边界的话,就看是否遇到非陆地--“0”的情况,则返回1
//如果已经访问过该节点,那么直接跳过
if(visited[row][col]) return 0;
int temp = 0;
visited[row][col] = true;
for (int way = 0;way < 4;way++){
int next_i = row + position[way][0];
int next_j = col + position[way][1];
//dfs向四周调用,并且加上对应需要的长度
temp += dfs_islandPerimeter(grid,next_i,next_j);
}
return temp;
}
}
_463岛屿的周长_逐一找边
package 代码随想录.图论;
public class _463岛屿的周长_逐一找边 {
int position[][] = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
/**
* 但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
* 计算这个岛屿的周长。
* @param grid
* @return
*/
public int islandPerimeter(int[][] grid) {
/*
grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。
但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
dfs,找到"1"开始visited,然后没有的方向或者处于边界的方向(即将越界)+1
否则,继续dfs
*/
int row = grid.length;
int col = grid[0].length;
int result = 0;
for (int i = 0; i < row; i++) {
for (int j = 0;j< col;j++){
if (grid[i][j] == 1){
for (int k = 0;k<4;k++){
//遍历四个方向
int next_i = i + position[k][0];
int next_j = j + position[k][1];
//如果可以超过边界,或者下一个寻找方向是河流“0”,那么就给周长加上1
if (next_i < 0 || next_j < 0 || next_i > grid.length-1 || next_j > grid[0].length -1 || grid[next_i][next_j] == 0){
result++;
continue;
}
}
}
}
}
return result;
}
}
_463岛屿的周长_岛屿与边的关系
package 代码随想录.图论;
public class _463岛屿的周长_岛屿与边的关系 {
//计算出总的岛屿数量,因为有一对相邻两个陆地,边的总数就减2,那么在计算出相邻岛屿的数量就可以了。
/**
* result = 岛屿数量 * 4 - cover * 2;
* @param grid
* @return
*/
public int islandPerimeter(int[][] grid) {
//岛屿数量,,,相邻两个陆地cover数量
int result = 0,landSum = 0 , coverSum = 0;
int row = grid.length;
int col = grid[0].length;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
//统计岛屿数量,在统计相邻两个陆地cover数量
//确定好一个方向即可,因为没有采用visited数组,因此必须规范遍历
if (grid[i][j] == 1) {
++landSum;
//这里选择统计每个节点的左边和上面的相邻两个陆地cover数量
if (i - 1 >= 0 && grid[i-1][j] == 1) coverSum++;
if (j - 1 >= 0 && grid[i][j-1] == 1) coverSum++;
}
}
}
return landSum * 4 - coverSum * 2;
}
}