leetcode岛屿类问题

岛屿类问题

问题基础

如何在二维矩阵中使用 DFS 搜索呢?如果你把二维矩阵中的每一个位置看做一个节点,这个节点的上下左右四个位置就是相邻节点,那么整个矩阵就可以抽象成一幅网状的「图」结构。

根据二叉树的遍历框架改写出二维矩阵的 DFS 代码框架:

// 二叉树遍历框架
void traverse(TreeNode root) {
    traverse(root.left);
    traverse(root.right);
}

// 二维矩阵遍历框架
void dfs(int[][] grid, int i, int j, boolean[][] visited) {
    int m = grid.length, n = grid[0].length;
    if (i < 0 || j < 0 || i >= m || j >= n) {
        // 超出索引边界
        return;
    }
    if (visited[i][j]) {
        // 已遍历过 (i, j)
        return;
    }
    // 进入节点 (i, j)
    visited[i][j] = true;
    dfs(grid, i - 1, j, visited); // 上
    dfs(grid, i + 1, j, visited); // 下
    dfs(grid, i, j - 1, visited); // 左
    dfs(grid, i, j + 1, visited); // 右
    visited[i][j] = false;
}

DFS

200. 岛屿数量

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        int ans = 0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='1'){
                    dfs(grid,i,j);
                    ans++;
                }
            }
        }
        return ans;
    }
    void dfs(vector<vector<char>>&grid, int i,int j){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n){
            return;
        }
        if(grid[i][j]=='0')
            return;
        grid[i][j]='0';
        dfs(grid,i+1,j);
        dfs(grid,i-1,j);
        dfs(grid,i,j+1);
        dfs(grid,i,j-1);
        return;
    }
};

694. 不同的岛屿数量

class Soultion694
{
public:
    Soultion694() {}
public:
    int numDistinctIslands(vector<vector<int>>& grid){
        int m = grid.size();
        int n = grid[0].size();
        unordered_map<string,int> hashmap;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    string res;
                    dfs(grid,i,j,res,666);
                    hashmap[res]++;
                }
            }
        }
        return hashmap.size();
    }
    void dfs(vector<vector<int>>& grid, int i, int j, string& str, int dir){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n){
            return;
        }
        if(grid[i][j]==0){
            return;
        }
        grid[i][j]=0;
        str += std::to_string(dir)+",";

        dfs(grid,i-1,j,str,1);
        dfs(grid,i+1,j,str,2);
        dfs(grid,i,j-1,str,3);
        dfs(grid,i,j+1,str,4);

        str += std::to_string(-dir)+",";
        return;
    }
};

695. 岛屿的最大面积

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        int ans = 0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    int area = 0;
                    dfs(grid,i,j,area);
                    ans = max(ans,area);
                }
            }
        }
        return ans;
    }

    void dfs(vector<vector<int>>& grid, int i,int j,int& area){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n)
            return;
        if(grid[i][j]==0)
            return;
        area++;
        grid[i][j]=0;
        dfs(grid,i-1,j,area);
        dfs(grid,i+1,j,area);
        dfs(grid,i,j-1,area);
        dfs(grid,i,j+1,area);
        return;
    }
};

711. Number of Distinct Islands II

class Solution711
{
public:
    Solution711() {}

    int numDistinctIslands2(vector<vector<int>>& grid){
        int m = grid.size();
        int n = grid[0].size();
        set<vector<pair<int,int>>> distinct;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    vector<pair<int,int>> pattern;
                    dfs(grid,pattern,i,j,i,j);
                    distinct.insert(normalize(pattern));
                }
            }
        }
        return distinct.size();
    }

    void dfs(vector<vector<int>>&grid, vector<pair<int,int>>& pattern, int i0, int j0, int i, int j){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n){
            return;
        }
        if(grid[i][j]<=0){
            return;
        }
        grid[i][j]=-1;
        pattern.emplace_back(i-i0,j-j0);
        static constexpr int dx[4] = {-1,1,0,0};
        static constexpr int dy[4] = {0,0,-1,1};
        for(int k=0;k<4;k++){
            dfs(grid,pattern ,i0,j0,i+dx[k],j+dy[k]);
        }
        return;
    }

    vector<pair<int,int>> normalize(vector<pair<int,int>> pattern){
        vector<vector<pair<int,int>>> ret(8,vector<pair<int,int>>());
        for(auto cur:pattern){
            int x = cur.first, y = cur.second;
            ret[0].emplace_back(x,y);
            ret[1].emplace_back(-x,y);
            ret[2].emplace_back(x,-y);
            ret[3].emplace_back(-x,-y);
            ret[4].emplace_back(y,x);
            ret[5].emplace_back(y,-x);
            ret[6].emplace_back(-y,x);
            ret[7].emplace_back(-y,-x);
        }
        for(int i = 0;i < 8; i++){
            sort(ret[i].begin(),ret[i].end());  // 对八种形状按照从上到下和从左到右进行排序 1的位置
            int r_offset = 0 - ret[i][0].first; // 将每种形状的最上边 最左边的1的位置记录为(0,0)
            int l_offset = 0 - ret[i][0].second; // 统一规规范化 最其中最小的
            for(int j=0;j<ret[i].size();j++){
                ret[i][j].first += r_offset;
                ret[i][j].second += l_offset;
            }
        }
        sort(ret.begin(),ret.end());
        return ret[0];
    }

};

1020. 飞地的数量

class Solution {
public:
    int numEnclaves(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();

        for(int i=0;i<m;i++){
            if(grid[i][0]==1){
                dfs(grid,i,0);
            }
            if(grid[i][n-1]==1){
                dfs(grid,i,n-1);
            }
        }
        for(int i=0;i<n;i++){
            if(grid[0][i]==1){
                dfs(grid,0,i);
            }
            if(grid[m-1][i]==1){
                dfs(grid,m-1,i);
            }
        }
        int count{0};
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                if(grid[i][j]==1){
                    count++;
                }
            }
        }
        return count;
    }
    void dfs(vector<vector<int>>&grid,int i,int j){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n)
            return;
        if(grid[i][j]==0)
            return;
        grid[i][j]=0;
        dfs(grid,i-1,j);
        dfs(grid,i+1,j);
        dfs(grid,i,j-1);
        dfs(grid,i,j+1);
    }
};

1254. 统计封闭岛屿的数目

class Solution {
public:
    int closedIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        for(int i=0;i<m;i++){
            if(grid[i][0]==0){
                dfs(grid,i,0);
            }
            if(grid[i][n-1]==0){
                dfs(grid,i,n-1);
            }
        }
        for(int i=0;i<n;i++){
            if(grid[0][i]==0){
                dfs(grid,0,i);
            }
            if(grid[m-1][i]==0){
                dfs(grid,m-1,i);
            }
        }
        int count{0};
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                if(grid[i][j]==0){
                    dfs(grid,i,j);
                    count++;
                }
            }
        }
        return count;

    }

    void dfs(vector<vector<int>>&grid, int i,int j){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n)
            return;
        if(grid[i][j]==1)
            return;
        grid[i][j]=1;
        dfs(grid,i-1,j);
        dfs(grid,i+1,j);
        dfs(grid,i,j-1);
        dfs(grid,i,j+1);
        return;
    }
};

1905. 统计子岛屿

class Solution {
public:
    int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
        int m = grid1.size();
        int n = grid1[0].size();
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid1[i][j]==0&&grid2[i][j]==1){
                    dfs(grid2,i,j);
                }
            }
        }
        int count{0};
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid2[i][j]==1){
                    dfs(grid2,i,j);
                    count++;
                }
            }
        }
        return count;
    }

    void dfs(vector<vector<int>>& grid2,int i,int j){
        int m = grid2.size();
        int n = grid2[0].size();
        if(i<0||i>=m||j<0||j>=n)
            return;
        if(grid2[i][j]==0)
            return;
        grid2[i][j]=0;
        dfs(grid2,i-1,j);
        dfs(grid2,i+1,j);
        dfs(grid2,i,j-1);
        dfs(grid2,i,j+1);
        return;
    }
};

463. 岛屿的周长

这道题目主要需要清楚,1格子的每条边被算作周长当且仅当这条边为网格边界或者相邻的另一个格子为水域。因此,可以遍历每个陆地格子,对其四个方向是否为边界或者水域,通过遍历就可以得到。

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        int ans = 0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    dfs(grid,i,j,ans);
                }
            }
        }
        return ans;
    }
    void dfs(vector<vector<int>>&grid, int i,int j,int& ans){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n){
            ans++;
            return;
        }
        if(grid[i][j]==0){
            ans++;
            return;
        }
        if(grid[i][j]==2)
            return;
        grid[i][j]=2;
        dfs(grid,i-1,j,ans);
        dfs(grid,i+1,j,ans);
        dfs(grid,i,j-1,ans);
        dfs(grid,i,j+1,ans);
        return;
    }
};

剑指 Offer II 105. 岛屿的最大面积

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        int ans = 0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    int area{0};
                    dfs(grid,i,j,area);
                    ans = max(area, ans);
                }
            }
        }
        return ans;
    }
    void dfs(vector<vector<int>>& grid, int i,int j,int& area){
        int m = grid.size();
        int n = grid[0].size();
        if(i<0||i>=m||j<0||j>=n){
            return;
        }
        if(grid[i][j]==0)
            return;
        grid[i][j]=0;
        area++;
        dfs(grid,i-1,j,area);
        dfs(grid,i+1,j,area);
        dfs(grid,i,j-1,area);
        dfs(grid,i,j+1,area);
        return;
    }
};

130. 被围绕的区域

class Solution {
public:
    void solve(vector<vector<char>>& board) {
        int m = board.size();
        int n = board[0].size();
        for(int i=0;i<m;i++){
            if(board[i][0]=='O')
                dfs(board,i,0,'#');
            if(board[i][n-1]=='O')
                dfs(board,i,n-1,'#');
        }
        for(int i=0;i<n;i++){
            if(board[0][i]=='O')
                dfs(board,0,i,'#');
            if(board[m-1][i]=='O')
                dfs(board,m-1,i,'#');
        }

        // for(int i=0;i<m;i++){
        //     for(int j=0;j<n;j++){
        //         if(board[i][j]=='O'){
        //             dfs(board,i,j,'X');
        //         }
        //     }
        // }

        // for(int i=0;i<m;i++){
        //     for(int j=0;j<n;j++){
        //         if(board[i][j]=='#'){
        //             dfs(board,i,j,'O');
        //         }
        //     }
        // }

        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(board[i][j]=='#'){
                    board[i][j]='O';
                }
                else if (board[i][j]=='O') {
                    board[i][j]='X';
                }
            }
        }

    }
    void dfs(vector<vector<char>>&board, int i,int j, char ch){
        int m = board.size();
        int n = board[0].size();
        if(i<0||i>=m||j<0||j>=n)
            return;
        if(board[i][j]==ch || board[i][j]=='X')
            return;
        board[i][j]=ch;
        dfs(board,i-1,j,ch);
        dfs(board,i+1,j,ch);
        dfs(board,i,j-1,ch);
        dfs(board,i,j+1,ch);
        return;
    }
};

827. 最大人工岛

class Solution {
public:
    inline bool inArea(const vector<vector<int>>& grid,int i,int j){
        return i>=0 && i<grid.size() && j>=0 && j<grid[0].size();
    }

    int dfs(vector<vector<int>>& grid, int i, int j, int index){
        if(!inArea(grid,i,j))
            return 0;
        if(grid[i][j]!=1)
            return 0;
        grid[i][j]=index;
        return (1+
                dfs(grid,i-1,j,index)+
                dfs(grid,i+1,j,index)+
                dfs(grid,i,j-1,index)+
                dfs(grid,i,j+1,index));
    }

    set<int> findNeighbour(const vector<vector<int>>& grid, int i, int j){
        set<int> hashset;
        if(inArea(grid,i-1,j)&&grid[i-1][j]!=0)
            hashset.insert(grid[i-1][j]);
        if(inArea(grid,i+1,j)&&grid[i+1][j]!=0)
            hashset.insert(grid[i+1][j]);
        if(inArea(grid,i,j-1)&&grid[i][j-1]!=0)
            hashset.insert(grid[i][j-1]);
        if(inArea(grid,i,j+1)&&grid[i][j+1]!=0)
            hashset.insert(grid[i][j+1]);
        return hashset;
    }

    int largestIsland(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        int index = 2;
        int maxArea = 0;
        if(m==0)
            return 1;
        unordered_map<int,int> hashmap;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==1){
                    int area = 0;
                    area = dfs(grid,i,j,index);
                    hashmap[index] = area;
                    index++;
                    maxArea = max(maxArea, area);
                }
            }
        }
        if(maxArea==0)
            return 1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]==0){
                    set<int> hashset = findNeighbour(grid,i,j);
                    if(hashset.empty())
                        continue;
                    int area = 1;
                    for(auto it=hashset.begin();it!=hashset.end();it++){
                        area += hashmap[*it];
                    }
                    maxArea = max(maxArea, area);
                }
            }
        }
        return maxArea;
    }
};

UF

305. 岛屿数量 II

class Solution305
{
public:
    class UF
    {
    public:
        int amounts;
        vector<int> parent;
        vector<int> size;

    public:
        UF() {}
        UF(int n){
            amounts = n;
            parent.resize(n);
            size.resize(n);
            for(int i=0;i<n;i++){
                parent[i]=i;
                size[i]=1;
            }
        }
        int find(int index){
            while (parent[index]!=index) {
                parent[index] = parent[parent[index]];
                index = parent[index];
            }
            return parent[index];
        }

        bool isconnected(int p,int q){
            int rootP = find(p);
            int rootQ = find(q);
            return rootP==rootQ;
        }
        int count(){
            return amounts;
        }
        void uion(int p,int q){
            int rootP = find(p);
            int rootQ = find(q);
            if(rootP==rootQ)
                return;
            if(size[rootP]>size[rootQ]){
                parent[rootQ] = rootP;
                size[rootP] += size[rootQ];
            }
            else {
                parent[rootP] = rootQ;
                size[rootQ] += size[rootP];
            }
            amounts--;
            return;
        }

    };
public:
    Solution305() {}
    vector<int> numIslands2(int m, int n,const vector<vector<int>>& positions){
        vector<int> parents(m*n,-1);
        vector<vector<int>> grid(m,vector<int>(n,0));
        vector<int> ans(positions.size(),0);
        static constexpr int dx[4] = {0,0,-1,1};
        static constexpr int dy[4] = {-1,1,0,0};
        int count = 0;
        for(int i=0;i<positions.size();i++){
            int cx = positions[i][0], cy = positions[i][1];
            int id = cx*n+cy;
            if(parents[id]!=-1){        // 重复添加
                ans[i] = count;
                continue;
            }
            grid[cx][cy]=1;     // 新添加
            parents[id]=id;
            count++;
            for(int k = 0;k<4;k++){
                int nx = cx + dx[k];
                int ny = cy + dy[k];
                int nxt_id = nx * n + ny;
                if(nx<0||nx>=m||ny<0||ny>=n||grid[nx][ny]==0||parents[nxt_id]==-1) // 单独的岛屿的父节点是自己
                    continue;
                else {
                    int rootid = findRoot(parents,id);
                    int rootnxt_id = findRoot(parents,nxt_id);
                    if(rootid!=rootnxt_id){             // 发现相邻岛屿 且和自身的父节点不同 可以进行合并  那么就不是新岛屿
                        parents[rootid]==rootnxt_id;
                        count--;
                    }
                }
            }
            ans[i] = count;
        }
        return ans;
    }

    int findRoot(vector<int>& parents, int index){
        while (parents[index]!=index) {
            parents[index] = parents[parents[index]];
            index = parents[index];
        }
        return index;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值