这道「岛屿题」用并查集做就体现出其威力了!

简介: 之前的岛屿题,用 DFS 和 BFS 来做要比用并查集更加好做并且高效,但是最对这一道题来说,用并查集要更加好做。

之前的岛屿题,用 DFS 和 BFS 来做要比用并查集更加好做并且高效,但是最对这一道题,827. 最大人工岛 来说,用并查集要更加好做。
【题目】给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。返回执行此操作后,grid 中最大的岛屿面积是多少?岛屿 由一组上、下、左、右四个方向相连的 1 形成。

题目要求是将一格 0 变成 1 之后再看最大的岛屿能够为多少,因此可以用上下左右分别判断岛屿的大小和当前的 0 组合记录最大的岛屿。思路如下:

  • 第一遍遍历 grid:把所有的岛屿都记录下来,并且通过 rank 可以获得岛屿的面积;
  • 第二遍遍历 grid:遇到为 0 的位置就记录将当前位置变为 1 之后,上下左右的岛屿面积连通起来的岛屿面积,具体做法:

    • 用一个变量 area = 1 记录面积;
    • 分别判断上下左右的位置是否为 1,如果为 1 的话获得该岛屿的面积,并累加到 area
    • 还要记得多一个变量 seen 来记录岛屿是否已经见过。因为有可能上下左右有属于同一个岛屿的;

首先把并查集实现了:

class UnionFind {
public:
    int count;
    vector<int> parent;
    vector<int> rank;

    UnionFind(int n) {
        count = n;
        parent = vector<int>(n);
        rank = vector<int>(n, 1);
        for (int i = 0; i < parent.size(); i++) {
            parent[i] = i;
        }
    }

    int Find(int x) {
        if (parent[x] != x) {
            parent[x] = Find(parent[x]);
        }
        return parent[x];
    }

    void Union(int x, int y) {
        int root_x = Find(x), root_y = Find(y);
        if (root_x == root_y) { return; }
        if (rank[root_x] >= rank[root_y]) {
            parent[root_y] = root_x;
            rank[root_x] += rank[root_y];
        } else {
            parent[root_x] = root_y;
            rank[root_y] += rank[root_x];
        }
    }
};

然后是题目主要逻辑:

class Solution {
public:
    int largestIsland(vector<vector<int>>& grid) {
        // 遍历整个 grid 创建并查集
        int n = grid.size();
        UnionFind uf(n * n);
        int dx[4] = {-1, 1, 0, 0};
        int dy[4] = {0, 0, -1, 1};
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    for (int k = 0; k < 4; k++) {
                        int nx = i + dx[k];
                        int ny = j + dy[k];
                        if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
                            uf.Union(i * n + j, nx * n + ny);
                        }
                    }
                }
            }
        }

        int maxArea = 0;
        // 遍历所有的 0, 并且判断如果将这个 0 变为 1 之后的最大面积是多少
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) { // 直接比较当前的面积大小
                    maxArea = max(maxArea, uf.rank[uf.Find(i * n + j)]);
                } else if (grid[i][j] == 0) {
                    int area = 1;  // 当前位置变为 1
                    set<int> seen;
                    for (int k = 0; k < 4; k++) {
                        int nx = i + dx[k];
                        int ny = j + dy[k];
                        if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
                            int root_x = uf.Find(nx * n + ny);
                            if (seen.count(root_x) == 0) {
                                area += uf.rank[root_x];
                                seen.insert(root_x);
                            }
                        }
                    }
                    maxArea = max(maxArea, area);
                }
            }
        }
        return maxArea;
    }
};

LeetCode 上的题解为:并查集的威力终于发挥出来了!【C++ 并查集】

目录
相关文章
|
人工智能
港科大等发布多模态图推理问答数据集GITQA
【2月更文挑战第14天】港科大等发布多模态图推理问答数据集GITQA
254 7
港科大等发布多模态图推理问答数据集GITQA
|
存储 人工智能 测试技术
具备实时数据更新能力的大语言模型——Larimar
【2月更文挑战第30天】Larimar是一种新型的人工智能研究,旨在解决大型语言模型的知识更新问题。通过引入分布式情景记忆机制,类似人脑海马体的功能,Larimar能动态更新知识而无需完全重训。在实验中,它在事实编辑基准测试中展现出高准确性和速度提升,比基础LLM快4到10倍。Larimar的精巧架构包含编码器、解码器和自适应记忆模块,能在多种场景下有效应用。该模型的记忆操作包括写入、读取和生成,且在序列事实编辑任务中表现出色,防止信息遗忘。
522 2
具备实时数据更新能力的大语言模型——Larimar
|
Linux iOS开发 UED
探索Qt折线图之美:一次详尽的多角度解析
探索Qt折线图之美:一次详尽的多角度解析
1664 0
idea实现protobuf的.proto文件编译成.java文件教程
1..proto文件语法高亮显示1.1 打开idea的插件列表1.2 下载protobuf辅助插件1.3 安装好后重启idea 在项目中新增配置生成环境 1.6.1
13886 0
|
开发框架 前端开发 Linux
开源项目推荐:C++ Web/Http Server/Rest开发框架(请重点关注Oat++和搜狗workflow)
开源项目推荐:C++ Web/Http Server/Rest开发框架(请重点关注Oat++和搜狗workflow)
4836 0
|
11月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
7月前
|
监控 关系型数据库 MySQL
如何解决 MySQL 数据库服务器 CPU 飙升的情况
大家好,我是 V 哥。当 MySQL 数据库服务器 CPU 飙升时,如何快速定位和解决问题至关重要。本文整理了一套实用的排查和优化套路,包括使用系统监控工具、分析慢查询日志、优化 SQL 查询、调整 MySQL 配置参数、优化数据库架构及检查硬件资源等步骤。通过一个电商业务系统的案例,详细展示了从问题发现到解决的全过程,帮助你有效降低 CPU 使用率,提升系统性能。关注 V 哥,掌握更多技术干货。
967 0
|
数据可视化
R语言中实现sem进行结构方程建模和路径图可视化(上)
R语言中实现sem进行结构方程建模和路径图可视化
|
人工智能 算法 定位技术
[AI aider] 打造终端AI搭档:Aider让编程更智能更有趣!
发现Aider,一个能在终端中与AI搭档编程的工具,让你的编程体验更智能、更有趣。
[AI aider] 打造终端AI搭档:Aider让编程更智能更有趣!
|
SQL 存储 缓存
老司机总结的12条 SQL 优化方案(非常实用)(一)
老司机总结的12条 SQL 优化方案(非常实用)
老司机总结的12条 SQL 优化方案(非常实用)(一)