用并查集解决「岛屿最大面积问题」

简介: 用并查集解决这个问题时间花费会比 DFS 和 BFS 更大,但是最主要的还是学习并查集的思想以及如何实现。

想要实现并查集,首先要先理解和实现两个最基本的函数 Find(int x)Union(int x, int y)

  • Find(int x) 实现的功能是查找 x 是属于哪一个集合;
  • Union(int x, int y) 是将 xy 弄成同一个集合;

数组 parent 是记录每个元素与哪一个元素属于同一个集合。当用 Find(x) 寻找的时候,如果 parent[x] == x 则证明当前元素是根元素,否则继续寻找 parent[x] 的根元素;

数组 rank 用来记录根元素所属于的集合中具有多少个元素,只有属于根元素位置上的数字有意义;

class UnionFind {
public:
    UnionFind(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) {
        // 寻找元素 x 的根元素
        if (parent[x] != x) {
            parent[x] = Find(parent[x]);
        }
        return parent[x];
    }
    
    void Union(int x, int y) {
        int root_x = Find(x);
        int 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];
        }
        count--;  // 让连接了一个, 让集合数减一
    }
    
private:
    int count;
    vector<int> parent;
    vector<int> rank;
}

用并查集解决岛屿最大面积问题

问题描述:

【题目】剑指 Offer II 105. 岛屿的最大面积:给定一个由 01 组成的非空二维数组 grid ,用来表示海洋岛屿地图。

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。如果没有岛屿,则返回面积为 0

// 首先把并查集类写出来
// 问题中的 grid 是一个二维的 vector, 并查集中用一维 vector 来处理
// 行数为 m, 列数为 n, grid[i][j] 对应在并查集中的位置就是 [i * n + j]
class UnionFind {
public: 
    // 构造函数
    UnionFind(int n) {
        count = n;  // 总共集合总数
        parent = vector<int>(n);
        rank = vector<int>(n);
        for (int i = 0; i < parent.size(); i++) {
            parent[i] = i;
            rank[i] = 1;
        }
    }
    
    // 返回根元素
    int Find(int x) {
        if (parent[x] != x) {
            parent[x] = Find(parent[x]);
        }
        return parent[x];
    }
    
    // 将 x 和 y 进行合并
    void Union(int x, int y) {
        int root_x = Find(x);
        int root_y = Find(y);
        // 如果 x, 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];
        }
        count--;  // 集合总数减 1
    }

    // 返回 rank 数组
    vector<int> get_rank() {
        return rank;
    }
    
    // 返回 parent 数组
    vector<int> get_parent() {
        return parent;
    }

private:
    vector<int> parent;
    vector<int> rank;
    int count;
};

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int dx[4] = {-1, 1, 0, 0};
        int dy[4] = {0, 0, -1, 1};
        int m = grid.size();
        if (m == 0) { return 0; }
        int n = grid[0].size();
        UnionFind uf = UnionFind(m * n);

        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 x = i + dx[k];
                        int y = j + dy[k];
                        if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) {
                            uf.Union(i * n + j, x * n + y);
                        }
                    }
                }
            }
        }
        
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    ans = max(ans, uf.get_rank()[i * n + j]);
                }
            }
        }
        return ans;
    }
};
用并查集解决这个问题时间花费会比 DFS 和 BFS 更大,但是最主要的还是学习并查集的思想以及如何实现。
目录
相关文章
|
机器学习/深度学习 算法
【机器学习】过拟合和欠拟合怎么判断,如何解决?(面试回答)
本文介绍了如何通过观察训练误差和验证误差来判断模型是否出现过拟合或欠拟合,并提供了相应的解决方案,包括增加数据、调整模型复杂度、使用正则化技术等。
1491 1
|
12月前
|
存储 弹性计算 安全
阿里云服务器ECS详解:云服务器是什么,云服务器优势和应用场景及价格参考
云服务器ECS是阿里云众多云产品中,最受用户关注的产品,阿里云服务器提供多样化的计算能力,支持x86、Arm架构,涵盖CPU、GPU等多种服务器类型,满足各种用户需求。本文为大家详细介绍阿里云服务器是什么?云服务器的优势和应用场景,以及最新价格情况,以供大家参考。
|
机器学习/深度学习 数据采集 算法
如何在一夜之间成为模型微调大师?——从零开始的深度学习修炼之旅,让你的算法功力飙升!
【10月更文挑战第5天】在机器学习领域,预训练模型具有强大的泛化能力,但直接使用可能效果不佳,尤其在特定任务上。此时,模型微调显得尤为重要。本文通过图像分类任务,详细介绍如何利用PyTorch对ResNet-50模型进行微调,包括环境搭建、数据预处理、模型加载与训练等步骤,并提供完整Python代码。通过调整超参数和采用早停策略等技巧,可进一步优化模型性能。适合初学者快速上手模型微调。
705 8
|
人工智能 搜索推荐 UED
Bot 商店 + 一键优化提示词 Prompt,开启AI新体验!| Botnow上新
Botnow 迎来了重大更新,新增了 Bot 商店功能,并优化了 Bot 编排,提升了 AI 使用效率。用户可在 Bot 商店中轻松浏览和体验各类官方及用户发布的 Bots,并可一键发布或下架自己的 Bot。此外,还推出了一键优化 Prompt 功能,帮助用户生成清晰、精准的指令,提升对话质量。新老用户快来体验吧![链接]
525 5
|
物联网 芯片 计算机视觉
树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)
树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)
树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)
|
测试技术 Go
|
关系型数据库 MySQL
Mysql连接无效(invalid connection)解决方案
Mysql连接无效(invalid connection)解决方案
2311 0
Mysql连接无效(invalid connection)解决方案
|
运维 Kubernetes Cloud Native
应用纳管和灰度发布:谐云基于 KubeVela 的企业级云原生实践
谐云通过类比事务的方式,将渲染过程分为正向和逆向,同时将首次纳管和真正的纳管动作进行了分离,完成了平台升级的同时,给应用的纳管行为留下了一定的可操作空间。
应用纳管和灰度发布:谐云基于 KubeVela 的企业级云原生实践
|
机器学习/深度学习 JSON 算法
TensorFlow Serving使用指南
TensorFlow Serving使用指南
865 0
|
传感器 前端开发 算法
蓝牙、wifi、zigbee和lora、NB-lot,通话信号,网络信号4G
蓝牙、wifi、zigbee和lora、NB-lot,通话信号,网络信号4G
蓝牙、wifi、zigbee和lora、NB-lot,通话信号,网络信号4G