数据结构与算法-12.岛屿数量

12、岛屿数量

题目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gwvZeHFm-1636269427428)(image-20211107145809371.png)]

12.0、广度优先遍历

从一个点开始,进行广播一样的遍历,比如示例1,发现第一个数是一个岛,那么从【0,0】开始广播,广播依次经过

【0,1】,【1,0】

【0,2】,【1,1】,【2,0】

【0,3】,【2,1】

【1,3】

每到一个地方,就把那个坐标对应的位置变为0

使用队列或者栈来存储下次广播到达的坐标

int numIslands0(vector<vector<char>>& grid) 
{
    stack <pair<int, int>> data;
    int rows = grid.size();
    int cols = grid[0].size();
    int result = 0;

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            if (grid[i][j] == '1')
            {
                result++;
                data.push({ i,j });
                while (!data.empty())
                {
                    pair<int, int> nowLocation = data.top();
                    data.pop();
                    grid[nowLocation.first][nowLocation.second] = '0';
                    if (nowLocation.first + 1 < rows && grid[nowLocation.first + 1][nowLocation.second] == '1')data.push({ nowLocation.first + 1,nowLocation.second });
                    if (nowLocation.second + 1 < cols && grid[nowLocation.first][nowLocation.second + 1] == '1')data.push({ nowLocation.first,nowLocation.second + 1 });
                    if (nowLocation.first - 1 >= 0 && grid[nowLocation.first - 1][nowLocation.second] == '1')data.push({ nowLocation.first - 1,nowLocation.second });
                    if (nowLocation.second - 1 >= 0 && grid[nowLocation.first][nowLocation.second - 1] == '1')data.push({ nowLocation.first,nowLocation.second - 1 });
                }
            }
        }

    }
    return result;
}
  • 时间复杂度:O(m n)m为行数,n为列数

  • 空间复杂度:O(min(m n))下次广播坐标最大就是个正方形的对角线

12.1、深度优先搜索

和广度不一样的是,广度是以广播形式一圈一圈向外展开,而深度是从一个方向一直进行到底,比如示例1

  • 先一直向右走到【0,3】
  • 向下走一格到【1,3】
  • 原路返回至【0,1】
  • 向下走到【2,1】
  • 想左走一格到【2,0】
  • 向上走一格到【1,0】
  • 原路返回至【0,1】
  • 回到【0,0】

没到一个地方,就把该坐标对应的值变为0

void deepSearch1(vector<vector<char>>& grid, int rowNum, int colNum)
{
    grid[rowNum][colNum] = '0';
    if (rowNum + 1 < grid.size() && grid[rowNum + 1][colNum] == '1')deepSearch(grid, rowNum + 1, colNum);
    if (colNum + 1 < grid[0].size() && grid[rowNum][colNum + 1] == '1')deepSearch(grid, rowNum, colNum + 1);
    if (rowNum - 1 >= 0 && grid[rowNum - 1][colNum] == '1')deepSearch(grid, rowNum - 1, colNum);
    if (colNum - 1 >= 0 && grid[rowNum][colNum - 1] == '1')deepSearch(grid, rowNum, colNum - 1);
}
int numIslands2(vector<vector<char>>& grid)
{
    int rows = grid.size();
    int cols = grid[0].size();
    int result = 0;

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            if (grid[i][j] == '1')
            {
                result++;
                deepSearch(grid, i, j);
            }
        }
    }
    return result;
}
  • 时间复杂度:O(m n)m为行数,n为列数

  • 空间复杂度:O(m n)最坏情况是m n,就是全都是岛最初的一条道走到黑,直到走完。

12.2、并查集(重点)

这个博主也是刚学,害怕误导,有兴趣的可以去网上找一下资料,这里仅仅放代码。

class UnionFind
{
    private:
    vector<int> parent;
    vector<int> rank;
    int count = 0;

    //查找父节点
    int find(int i)
    {
        return parent[i] == i ? i : (parent[i] = find(parent[i]));
    }

    public:
    UnionFind(vector<vector<char>>& grid)
    {
        int rows = grid.size();
        int cols = grid[0].size();
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                if (grid[i][j] == '1')
                {
                    parent.push_back(i * cols + j);
                    count++;
                }
                else
                    parent.push_back(-1);
                rank.push_back(0);
            }
        }
    }

    //按秩合并
    void merge(int x, int y)
    {   
        int rootx = find(x);
        int rooty = find(y);
        if (rootx != rooty)
        {
            if (rank[rootx] <= rank[rooty])
                parent[rootx] = rooty;
            else
                parent[rooty] = rootx;
            if (rank[rootx] == rank[rooty])rank[rootx]++;
            count--;
        }
    }

    //返回集合个数
    int getCount()
    {
        return count;
    }
};


//并查集
int numIslands2(vector<vector<char>>& grid)
{
    int rows = grid.size();
    int cols = grid[0].size();
    UnionFind unionFind(grid);

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            if (grid[i][j] == '1')
            {
                grid[i][j] = '0';
                if (i + 1 < rows && grid[i + 1][j] == '1')unionFind.merge(i * cols + j, (i + 1) * cols + j);
                if (j + 1 < cols && grid[i][j + 1] == '1')unionFind.merge(i * cols + j, i * cols + j + 1);
            }
        }
    }
    return unionFind.getCount();
}
  • 时间复杂度:O(m n)其实还应该乘以每次的find时间,但由于是常量(不大于5),所以忽略

  • 空间复杂度:O(m n)并查集需要储存一个parent和一个rank

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值