首页 > 编程语言 >【每日一题】【并查集】【力扣】695.岛屿的最大面积 C++

【每日一题】【并查集】【力扣】695.岛屿的最大面积 C++

时间:2024-08-04 09:54:46浏览次数:8  
标签:pre 695 int 查集 岛屿 C++ pa grid find

力扣695. 岛屿的最大面积

695.岛屿的最大面积

题目描述

给你一个大小为 m × n m \times n m×n 的二进制矩阵 g r i d grid grid 。

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

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

样例 #1

样例输入 #1

grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]

样例输出 #1

6

样例 #2

样例输入 #2

grid = [[0,0,0,0,0,0,0,0]]

样例输出 #2

0

提示

m = = g r i d . l e n g t h n = = g r i d [ i ] . l e n g t h 1 < = m , n < = 50 g r i d [ i ] [ j ] 为 0 或 1 。 m == grid.length\\ n == grid[i].length\\ 1 <= m, n <= 50\\ grid[i][j] 为 0 或 1。 m==grid.lengthn==grid[i].length1<=m,n<=50grid[i][j]为0或1。

做题思路

这道题的要点就在于如何计算每一个岛屿的面积。

因为已知上下左右相邻土地为算为同一岛屿。

假设能知道该土地属于哪一个岛屿,然后将同一岛屿的土地相加,就可以得到这块岛屿的面积。

那么恭喜你解锁了本题并查集的做法。

并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。

恰好适用于上面的归属问题思路。

首先我们将所有的土地各自归为一个岛屿。

再从上到下从左到右遍历全图。
如果碰到了土地,再看相邻的四个格子是不是土地,如果是那么就将这几个都合并在一个集合(岛屿)里面。
直到跑完全图,在算一次所有岛屿的最大面积即可。

但其实可以发现如果碰到了土地不需要看完相邻的四个格子,只需要看左边一个和上面一个。因为是从上到下从左到右遍历全图,下面和右边的格子随后会遍历到,并且也看左边和上面,可以容易证明不会拉下岛屿的每一寸土地。

时间复杂度分析

最多跑完四次全图 O ( 4 n × m ) O(4n\times m) O(4n×m)
实际上初始化和合并步骤可以合在一起 O ( 3 n × m ) O(3n\times m) O(3n×m)

伪代码

在这里插入图片描述

代码

class Solution {
public:
    int pre[50][50];
    int pa[2501];
    int cnt[2501] = {0};
    int find(int x){return pa[x] == x ? x : pa[x] =find(pa[x]);}
    void unite(int x,int y){pa[find(x)] = find(y);}
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int k = 0;
        //init
        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[i].size();j++){
                pre[i][j] = ++k;
                pa[k] = k;
            }
        }

        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[i].size();j++){
                if(grid[i][j]){
                    if(i > 0 && grid[i-1][j])unite(pre[i][j],pre[i-1][j]);
                    if(j > 0 && grid[i][j-1])unite(pre[i][j],pre[i][j-1]);
                }
            }
        }
        int ans = 0;
        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[i].size();j++){
                if(grid[i][j]){
                    cnt[find(pre[i][j])]++;
                }
            }
        }
        for(int i=1;i<=grid.size()*grid[0].size();i++)
            ans = max(ans,cnt[i]);
        return ans;
    }
};

初始化和合并步骤合在一起后的代码

class Solution {
public:
    int pre[50][50];
    int pa[2501];
    int cnt[2501] = {0};
    int find(int x){return pa[x] == x ? x : pa[x] =find(pa[x]);}
    void unite(int x,int y){pa[find(x)] = find(y);}
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int k = 0;
        //init
        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[i].size();j++){
                pre[i][j] = ++k;
                pa[k] = k;
                if(grid[i][j]){
                    if(i > 0 && grid[i-1][j])unite(pre[i][j],pre[i-1][j]);
                    if(j > 0 && grid[i][j-1])unite(pre[i][j],pre[i][j-1]);
                }
            }
        }
        int ans = 0;
        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[i].size();j++){
                if(grid[i][j]){
                    cnt[find(pre[i][j])]++;
                }
            }
        }
        for(int i=1;i<=grid.size()*grid[0].size();i++)
            ans = max(ans,cnt[i]);
        return ans;
    }
};

标签:pre,695,int,查集,岛屿,C++,pa,grid,find
From: https://blog.csdn.net/weixin_72899100/article/details/140834057

相关文章

  • C++ //练习 16.27 对下面每条带标签的语句,解释发生了什么样的实例化(如果有的话)。如果
    C++Primer(第5版)练习16.27练习16.27对下面每条带标签的语句,解释发生了什么样的实例化(如果有的话)。如果一个模板被实例化,解释为什么;如果未实例化,解释为什么没有。template<typenameT>classStack{};voidf1(Stack<char>); //(a)classExercise{ Stack<dou......
  • c动态加载c/c++ so并调用其中的函数或者子类实现
    在不少服务器应用中,会采用插件化或者模块化的体系实现具体的业务功能,比如mysql支持插件化体系,nginx采用模块化体系。总得来说,很多时候,因为扩展性,系统会采用动态加载so的方式扩展业务功能,而主框架不需要每次新增功能就不得不重新编译,很多时候,对于二进制发行的应用来说,不可能这......
  • C++ //练习 15.31 已知s1、s2、s3和s4都是string,判断下面的表达式分别创建了什么样的
    C++Primer(第5版)练习15.31练习15.31已知s1、s2、s3和s4都是string,判断下面的表达式分别创建了什么样的对象:(a)Query(s1)|Query(s2)&~Query(s3);(b)Query(s1)|(Query(s2)&~Query(s3));(c)(Query(s1)&(Query(s2))|(Query(s3)&Query(s4)));......
  • C++ //练习 16.14 编写Screen类模板,用非类型参数定义Screen的高和宽。
    C++Primer(第5版)练习16.14练习16.14编写Screen类模板,用非类型参数定义Screen的高和宽。环境:LinuxUbuntu(云服务器)工具:vim 代码块template<intH,intW>classScreen{public:usingpos=string::size_type;Screen()=default;Screen(cha......
  • C++ //练习 16.16 将StrVec类(参见13.5节,第465页)重写为模板,命名为Vec。
    C++Primer(第5版)练习16.16练习16.16将StrVec类(参见13.5节,第465页)重写为模板,命名为Vec。环境:LinuxUbuntu(云服务器)工具:vim 代码块#include<iostream>#include<memory>#include<utility>usingnamespacestd;template<typenameT>classVec{ public:......
  • 【C++】多态 - 含3个案例
    目录一、多态分类二、多态区别三、多态基本语法四、多态原理五、案例1:计算机类六、纯虚函数和抽象类七、案例2:制作饮品八、虚析构和纯虚析构九、案例3:电脑组装需求分析及实现多态是C++面向对象三大特性之一一、多态分类①静态多态:函数重载、运算符重载、复用函......
  • C++__位运算符:异或运算符 ^
    目的:     了解异或运算符的定义、性质及用法。定义:    二元运算符,符号为^,与位与、位或不同的是,它在二进制中为相同为0,不同为1。而且它还满足这几种运算规则:        1、任何数^0都等于它本身;    2、两个相同的数异或结果为0;    ......
  • C++自定义接口类设计器之模板代码生成四
    关键代码QStringListmultis=templateStr.split('\n');boolstartConfig=false;boolstartVar=false;boolstartTemplate=false;for(constauto&line:multis){if(startConfig){if(line.trimmed().st......
  • c++__位运算符:位与运算符&
    目的:了解位与运算符并加深对它的运用定义:一种二元运算符,符号为&,运用于二进制数中,特性为有0为0。#include<iostream>usingnamespacestd;intmain(){inta=0b1010;//10intb=0b0110;//6//a&b=0b0010;2cout<<(a&b)<<endl;}应用:1、判断奇偶性......
  • C++实现静态链表
    #include<iostream>usingnamespacestd;//定义静态链表的最大容量constintMAX_SIZE=100;//节点类classNode{public:intdata;//节点存储的数据intnext;//节点指向下一个节点的索引(在数组中的位置)//默认构造函数Node():data(0......