463. 岛屿的周长

文章讲述了如何解决LeetCode题目463——岛屿的周长问题,介绍了三种不同的解法,包括遍历四个方向判断是否为陆地、统计陆地数量和相邻陆地数量,以及使用深度优先搜索(DFS)的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:

在这里插入图片描述

463. 岛屿的周长

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;
    }
}

错误经验吸取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值