この「島問題」は組み合わせとチェックで威力を発揮!

前の島の問題では、ユニオン検索を使用するよりも DFS と BFS を使用した方が簡単で効率的ですが、この問題では、827. 最大の人工島であるため、ユニオン検索を使用する方が簡単です。[タイトル] サイズ のバイナリ行列が
与えられます1 に変更できるのは 0 のグリッド 1 つだけです。これを実行した後、の最大の島の面積はどこになりますか? 1 のグループが上下左右の 4 方向につながって形成されます。n x ngridgrid岛屿

問題の要件は、グリッド 0 を 1 に変更し、最大の島がどのくらいの大きさになるかを確認することです。したがって、島の大きさと現在の 0 を上下左右を使用して判断できます。組み合わせて最大の島を記録します。考え方は次のとおりです。

  • 最初の横断grid: すべての島を記録し、rank島の面積を取得します。
  • 2回目の横断grid:位置0に遭遇した場合、現在位置を1に変更した後、上下左右の島の面積で結ばれた島の面積を記録します。 具体的な方法は以下のとおりです。
    • 変数を使用してarea = 1エリアを記録します。
    • 上下左右の位置が1かどうかを判定し、1であれば島の面積を取得して;に加算しますarea
    • seenまた、島が見られたかどうかを記録する変数を追加することも忘れないでください。同じ島に属する上下左右の島が存在する可能性があるため、

最初に共用体検索セットを実装します。

class UnionFind {
    
    
public:
    int count;
    vector<int> parent;
    vector<int> rank;

    UnionFind(int 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) {
    
    
        if (parent[x] != x) {
    
    
            parent[x] = Find(parent[x]);
        }
        return parent[x];
    }

    void Union(int x, int y) {
    
    
        int root_x = Find(x), 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];
        }
    }
};

次に、トピックの主なロジックは次のとおりです。

class Solution {
    
    
public:
    int largestIsland(vector<vector<int>>& grid) {
    
    
        // 遍历整个 grid 创建并查集
        int n = grid.size();
        UnionFind uf(n * n);
        int dx[4] = {
    
    -1, 1, 0, 0};
        int dy[4] = {
    
    0, 0, -1, 1};
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < n; j++) {
    
    
                if (grid[i][j] == 1) {
    
    
                    for (int k = 0; k < 4; k++) {
    
    
                        int nx = i + dx[k];
                        int ny = j + dy[k];
                        if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
    
    
                            uf.Union(i * n + j, nx * n + ny);
                        }
                    }
                }
            }
        }

        int maxArea = 0;
        // 遍历所有的 0, 并且判断如果将这个 0 变为 1 之后的最大面积是多少
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < n; j++) {
    
    
                if (grid[i][j] == 1) {
    
     // 直接比较当前的面积大小
                    maxArea = max(maxArea, uf.rank[uf.Find(i * n + j)]);
                } else if (grid[i][j] == 0) {
    
    
                    int area = 1;  // 当前位置变为 1
                    set<int> seen;
                    for (int k = 0; k < 4; k++) {
    
    
                        int nx = i + dx[k];
                        int ny = j + dy[k];
                        if (nx >= 0 && nx < n && ny >= 0 && ny < n && grid[nx][ny] == 1) {
    
    
                            int root_x = uf.Find(nx * n + ny);
                            if (seen.count(root_x) == 0) {
    
    
                                area += uf.rank[root_x];
                                seen.insert(root_x);
                            }
                        }
                    }
                    maxArea = max(maxArea, area);
                }
            }
        }
        return maxArea;
    }
};

LeetCode の問題の解決策は次のとおりです。ユニオン検索の力がついに発揮されます。【C++とチェックセット】

おすすめ

転載: blog.csdn.net/weixin_39679367/article/details/128486802