Leetcode 200:岛屿数量

Leetcode 200:岛屿数量

200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

示例 2:

输入:grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出:3

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 300
  • grid[i][j] 的值为 '0''1'

代码均为ACM模式

BFS:

#include <bits/stdc++.h>
using namespace std;
void bfs(vector<vector<char>> &grid, int i, int j)
{
    int m = grid.size();
    int n = grid[0].size();
    queue<pair<int, int>> q;
    q.push({i, j});
    grid[i][j] = '0';

    int dx[] = {-1, 0, 0, 1};
    int dy[] = {0, -1, 1, 0};

    while (!q.empty())
    {
        auto [x, y] = q.front();
        q.pop();

        for (int i = 0; i < 4; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == '1')
            {
                q.push({nx, ny});
                grid[nx][ny] = '0';
            }
        }
    }
}

int numcnt(vector<vector<char>> &grid)
{
    if (grid.empty())
        return 0;
    int cnt = 0;
    int m = grid.size();
    int n = grid[0].size();
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (grid[i][j] == '1')
            {
                bfs(grid, i, j);
                cnt++;
            }
        }
    }
    return cnt;
}
int main()
{
    int n, m;
    cin >> m >> n;
    vector<vector<char>> grid(m, vector<char>(n));
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> grid[i][j];
        }
    }

    int res = numcnt(grid);
    cout << res << endl;

    return 0;
}

DFS:

#include <bits/stdc++.h>
using namespace std;

int m, n;
int dx[] = {-1, 0, 0, 1}; // 上、左、右、下
int dy[] = {0, -1, 1, 0};

void dfs(vector<vector<char>> &grid, int x, int y) {
    grid[x][y] = '0'; // 标记为已访问
    for (int k = 0; k < 4; ++k) {
        int nx = x + dx[k];
        int ny = y + dy[k];
        if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == '1') {
            dfs(grid, nx, ny);
        }
    }
}

int numIslands(vector<vector<char>> &grid) {
    int count = 0;
    m = grid.size();
    n = grid[0].size();
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            if (grid[i][j] == '1') {
                dfs(grid, i, j);
                count++;
            }
        }
    }
    return count;
}

int main() {
    cin >> m >> n;
    vector<vector<char>> grid(m, vector<char>(n));
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
            cin >> grid[i][j];

    cout << numIslands(grid) << endl;
    return 0;
}

并查集

#include <bits/stdc++.h>
using namespace std;

int m, n;
int dx[] = {-1, 0, 0, 1};
int dy[] = {0, -1, 1, 0};

vector<int> parent, rank;

int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]); // 路径压缩
    return parent[x];
}

void unite(int x, int y) {
    int rootX = find(x);
    int rootY = find(y);
    if (rootX == rootY) return;

    if (rank[rootX] < rank[rootY]) {
        parent[rootX] = rootY;
    } else if (rank[rootX] > rank[rootY]) {
        parent[rootY] = rootX;
    } else {
        parent[rootY] = rootX;
        rank[rootX]++;
    }
}

int numIslands(vector<vector<char>> &grid) {
    m = grid.size();
    n = grid[0].size();
    parent.resize(m * n);
    rank.resize(m * n, 0);

    int count = 0;

    // 初始化
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            int id = i * n + j;
            if (grid[i][j] == '1') {
                parent[id] = id;
                count++;
            }
        }
    }

    // 合并相邻陆地
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            if (grid[i][j] == '1') {
                for (int k = 0; k < 4; ++k) {
                    int ni = i + dx[k];
                    int nj = j + dy[k];
                    if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == '1') {
                        int id1 = i * n + j;
                        int id2 = ni * n + nj;
                        if (find(id1) != find(id2)) {
                            unite(id1, id2);
                            count--;
                        }
                    }
                }
            }
        }
    }
    return count;
}

int main() {
    cin >> m >> n;
    vector<vector<char>> grid(m, vector<char>(n));
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j)
            cin >> grid[i][j];

    cout << numIslands(grid) << endl;
    return 0;
}

维度DFSBFS
搜索结构栈(递归实现)队列
内存消耗深度大时递归栈可能爆栈需要队列,空间开销稳定
实现难度简单,几行递归代码稍复杂,需要管理队列
扩展顺序先深入一条路径再回溯逐层扩展,先近后远
适用场景小地图、连通块较少大地图、连通块较多、避免栈溢出
算法时间复杂度空间复杂度
DFSO(m × n)O(m × n)(递归栈深度)
BFSO(m × n)O(m × n)(队列大小)
Union-FindO(m × n * α(mn))O(m × n)(parent数组)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值