岛屿类问题

本文讨论了如何在给定的二维字符网格中快速计算岛屿数量和每个岛屿的周长。首先介绍了基于深度优先搜索(DFS)的传统解决方案,随后提出了一种更简洁的方法,仅通过遍历网格边界即可统计岛屿周长,避免了不必要的递归。这两种方法对比,展示了简化版的高效性。
摘要由CSDN通过智能技术生成

200.Number of Islands
Given an m x n 2D binary grid grid which represents a map of '1’s (land) and '0’s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:
Input: grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
Output: 1

Example 2:
Input: grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
Output: 3

Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] is ‘0’ or ‘1’.

class Solution {
    public int numIslands(char[][] grid) {
        if (grid == null)
            return 0;

        int rows = grid.length;
        int cols = grid[0].length;
        int ans = 0;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                ans += dfs(grid, i, j);
            }
        }

        return ans;
    }

    public int dfs(char[][] grid, int r, int c) {
    	// 若出界则直接退出
        if (r == grid.length || c == grid[0].length
            || r < 0 || c < 0)
            return 0;
		// 若是水也直接退出
        if (grid[r][c] == '0')
            return 0;
        // 给访问过的小岛做标记
        // 若无此标记则会一直兜圈
        grid[r][c] = '0';

        dfs(grid, r-1, c);
        dfs(grid, r+1, c);
        dfs(grid, r, c-1);
        dfs(grid, r, c+1);
		// 递归的访问一个小岛的上下左右四个方向后
		// 返回值1, 表示一个大岛屿
        return 1;
    }
}

463. Island Perimeter
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] is 0 or 1.

由于前几天做过200.Number of Islands这道题,自然而然就想到在dfs时顺便统计边数,怎么个统计法嘞?

一个岛屿的周长其实就是与岛屿方格相邻的水方格的数量
(这里的水方格既包括在grid里的, 当然也包括grid外的)

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        int cnt = 0;

        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] != 0 && grid[i][j] != -1)
                    cnt = dfs(grid, i, j);
            }
        }
        return cnt;
    }

    int dfs(vector<vector<int>>& grid, int r, int c) {
		
        if (r<0 || c<0 || r==grid.size() || c==grid[0].size())
            return 1;

        if (grid[r][c] == 0)
            return 1;
        if (grid[r][c] == -1)
            return 0;
        grid[r][c] = -1;

        

        return dfs(grid, r+1, c) +
            dfs(grid, r-1, c) +
            dfs(grid, r, c+1) +
            dfs(grid, r, c-1);
    }
};
// 时间复杂度: O(mn)
// 空间复杂度: O(mn)

但用dfs属实是多此一举 -e-

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        int rows = grid.size();
        int cols = grid[0].size();
        int ans = 0;

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 1) {
                    if (0==i || grid[i-1][j]==0) ans++; // 上
                    if (rows-1==i || grid[i+1][j]==0) ans++; // 下
                    if (0==j || grid[i][j-1]==0) ans++; // 左
                    if (cols-1==j || grid[i][j+1]==0) ans++; // 右
                }
            }
        }

        return ans;
    }
};
// 时间复杂度: O(mn)
// 空间复杂度: O(1)

to be continued …

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值