机考刷题之 10 LeetCode 200 岛屿数量

题目

分析

思路一

正向去做,使用并查集算法。也就是说去遍历每个元素,把相连的陆地加入同一个集合,然后将总的块数减一,最后减去水块数就是岛屿数。

关于并查集,我是看的卡尔的视频

代码

cpp 复制代码
class UnionFind {
private:
    vector<int> parent;
    vector<int> rank;
    int count; // 连通分量数量
    
public:
    UnionFind(int size) {//初始化
        parent.resize(size);
        rank.resize(size, 0);
        count = size;
        for (int i = 0; i < size; i++) {
            parent[i] = i;
        }
    }
    
    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), rootY = find(y);
        if (rootX != rootY) {
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootY] = rootX;
                rank[rootX]++;
            }
            count--;//总块数--,这个数后面减去水块数就是岛屿块
        }
    }
    
    int getCount() const {
        return count;
    }
};
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
          if (grid.empty() || grid[0].empty()) return 0;
    
    int m = grid.size(), n = grid[0].size();
    UnionFind uf(m * n);
    int waterCount = 0; // 水格子的数量
    
    // 方向数组:上下左右
    vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == '0') {
                waterCount++;
                continue;
            }
            
            // 检查四个方向
            for (auto& dir : directions) {
                int ni = i + dir.first;
                int nj = j + dir.second;
                
                if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == '1') {
                    uf.unite(i * n + j, ni * n + nj);
                }
            }
        }
    }
    
    return uf.getCount() - waterCount;
    }
};

结果

思路二

反向来做,遇到可能是岛屿的陆地,就消去它,此时岛屿数量加一,在岛屿数量加1以后,递归地检查周围是否有陆地,如果有,那么就消去它们,所以只要检查到有一个可能的岛屿路地块,那么他以及周围的陆地块都会被消除,再遍历后面的块时,只要是新的陆地块就一定是另外独立的岛屿。

代码

cpp 复制代码
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) 
    {
        int counter = 0;
        for(int i=0; i<grid.size(); i++)
        {
            for(int j=0; j<grid[0].size(); j++)
            {
                if(grid[i][j]=='1')
                {
                    searchIsland(grid, i, j);//检查到新的独立陆地
                    ++counter;
                }
            }
        }
        return counter;
    }
    void searchIsland(vector<vector<char>>& grid, int i, int j)
    {//递归地消去周围陆地
        grid[i][j]='0';
        if(i>0 && grid[i-1][j]=='1') searchIsland(grid, i-1, j);
        if(j>0 && grid[i][j-1]=='1') searchIsland(grid, i, j-1);
        if(i<grid.size()-1 && grid[i+1][j]=='1') searchIsland(grid, i+1, j);
        if(j<grid[0].size()-1 && grid[i][j+1]=='1') searchIsland(grid, i, j+1);
    }
};
相关推荐
南风知我意95716 小时前
【重构思维】用位运算做权限管理
前端·面试·职场和发展·性能优化·重构
黄昏回响16 小时前
计算机系统基础知识(十四):软件篇之计算机网络详解
计算机网络·程序人生·面试·职场和发展·改行学it
ZPC821016 小时前
相机接入ROS2 流程及问题排查
人工智能·算法·机器人
2501_9403152616 小时前
【无标题】两个相同字符串中不同字符的个数
算法·哈希算法·散列表
6Hzlia16 小时前
【Hot 100 刷题计划】 LeetCode 54. 螺旋矩阵 | C++ 模拟法题解
c++·leetcode·矩阵
算法鑫探16 小时前
显示器插座最短连线算法(蓝桥杯十六届C组编程题第二题)
c语言·数据结构·算法·排序算法·新人首发
akarinnnn16 小时前
【DAY15】:深⼊理解指针(6)
算法
float_com16 小时前
LeetCode 88. 合并两个有序数组
leetcode
水蓝烟雨16 小时前
LeetCode刷题笔记:合并两个有序链表(0021)
笔记·leetcode·链表
Lauren_Blueblue16 小时前
第十六届蓝桥杯省赛Python研究生组-C变换数组
python·算法·蓝桥杯·编程基础