Graph Theory Algorithm (6): LeetCode Graph Theory Algorithm Exercise (785. Judging Bipartite Graph, 695. Maximum Area of Island, Floodfill Algorithm, Union Check)

The content of this chapter is implemented in java, Github code warehouse: https://github.com/ZhekaiLi/Code/tree/main/Graph/src

Viewing the pictures in the article may require scientific Internet access!Because github is used to manage pictures, if there is a situation that cannot be loaded, please turn over the wall

[Reference] imooc Mr. Bobo: Fun Algorithm Series - Graph Theory Essentials for Interview and Promotion (Java Edition)

[Links to previous blogs]
Graph Theory Algorithms (1, 2): Classification of Graphs, Basic Concepts of Graphs (Undirected Graphs and Directed Graphs, Unweighted Graphs, Acyclic Graphs, Complete Graphs, Bipartite Graphs; Simple Graphs, Connected Graphs Components, spanning tree of graphs, subgraphs and parent graphs)
graph theory algorithm (3): basic representation of graphs (adjacency matrix, adjacency list, comparison of adjacency matrix and adjacency list)
graph theory algorithm (4): depth first of graphs Traversal DFS
Graph Theory Algorithm (5): Graph Breadth First Traversal BFS
Graph Theory Algorithm (6): LeetCode Graph Theory Algorithm Exercise (785. Judgment of Bipartite Graph, 695. Maximum Area of ​​Island, Floodfill Algorithm, Union Check)

6 LeetCode Graph Theory Algorithm Exercises

785. Judging Bipartite Graphs

You can refer to Section 4.4

java implementation: LeetCode785_me.java (the author used BFS)

695. Maximum area of ​​islands

The core of this problem is graph modeling, which is to extract point and edge information from the two-dimensional array given by the title. Our goal is to put the following matrix

[[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]]

Converted to

// AdjList[i] 储存结点i的邻接点
AdjList = [[1, 4, 8], [2, 7, 9], ...]

However, the nodes in the traditional adjacency list are represented as integers, while in the stem matrix, the nodes are represented by two-dimensional position parameters. The main steps are as follows:
(1) Map the node information from two-dimensional to one-dimensional



(2) Determine whether any node has adjacent points



(3) According to the previously written algorithm for solving the connected components of undirected graphs, complete the main body of the code

You can refer to Section 4.1

java implementation v1: LeetCode695_me.java(LeetCode shows that I beat 5.3% of users..., what a piece of crap. It may be that some relatively complex data structures are used, but in terms of logic, I personally feel that it is quite OK)
java implementation v2: LeetCode695.java(Better code example)
First convert the 2D matrix to HashSettype graph information, then use dfs. Core code:

private int[][] dirs = {
    
    {
    
    -1, 0}, {
    
    0, 1}, {
    
    1, 0}, {
    
    0, -1}}; // 四连通

private HashSet<Integer>[] constructGraph(){
    
    
    HashSet<Integer>[] g = new HashSet[R * C];
    for (int i = 0; i < g.length; i++)
        g[i] = new HashSet<>();

    for (int v = 0; v < g.length; v++) {
    
    
        int x = v / C, y = v % C; // 将一维信息转化为二维坐标
        if (grid[x][y] == 1) {
    
    
            for (int d = 0; d < 4; d++) {
    
    
                int nextx = x + dirs[d][0], nexty = y + dirs[d][1];
                if (inArea(nextx, nexty) && grid[nextx][nexty] == 1){
    
    
                    int next = nextx * C + nexty;
                    g[v].add(next);
                }}}}
    return g;
}

private int dfs(int v){
    
    
    visited[v] = true;
    int res = 1;
    for(int w: G[v]){
    
    
        if(!visited[w])
            res += dfs(w);
    }
    return res;
}

java implementation v3: LeetCode695_plus.java
Directly use the input two-dimensional matrix to save the graph information, and transform the dfs to make it suitable for two-dimensional input. Core code:

private int dfs(int x, int y){
    
    
    visited[x][y] = true;
    int res = 1;
    for(int d = 0; d < 4; d++){
    
    
        int nextx = x + dirs[d][0], nexty = y + dirs[d][1];
        if(inArea(nextx, nexty) && !visited[nextx][nexty] && grid[nextx][nexty] == 1)
            res += dfs(nextx, nexty);
    }
    return res;
}

6.1 floodfill algorithm

The last piece of code in the previous section (java implementation v3) is also called the floodfill algorithm, which is essentially the same as dfs, except that the original method of propagation based on edges is changed to propagation in four directions in the coordinate system. . The example is as follows:



Application of floodfill

Magic wand and minesweeper game in ps



Related questions in LeetCode

200. Number of islands
1020. Number of enclaves
130. Surrounded area
733. Image rendering (floodfill)
1034. Border coloring
529. Minesweeper game
827. Largest artificial island [Hard]

6.2 Connectivity and Unions

class UF{
    
    
    private int[] parent;

    public UF(int n){
    
    
        parent = new int[n];
        for(int i = 0 ; i < n ; i ++)
            parent[i] = i;
    }

    public int find(int p){
    
    
        if( p != parent[p] )
            parent[p] = find( parent[p] );
        return parent[p];
    }

    public boolean isConnected(int p , int q){
    
    
        return find(p) == find(q);
    }

    public void unionElements(int p, int q){
    
    
        int pRoot = find(p);
        int qRoot = find(q);
        if( pRoot == qRoot )
            return;
        parent[pRoot] = qRoot;
    }
}

The following will show the creation and running process of the union query set in a combination of diagram and code:

UF uf = new UF(6);


uf.unionElements(2, 1);
uf.unionElements(3, 1);
uf.unionElements(5, 4);
uf.unionElements(6, 4);


uf.unionElements(4, 1);


It should be noted that find(int p)the function can not only return the root node of node p, but also directly change the parent node of node p to its root node each time it runs. Such a functional implementation can avoid a long list of connections

Further, we can improve the UFclass to support finding the number of elements in the collection of any element

class UF{
    
    
    private int[] parent;
    private int[] sz; // 1. 我们需要一个 sz 数组,存储以第 i 个元素为根节点的集合的元素个数。

    public UF(int n){
    
    
        parent = new int[n];
        sz = new int[n];
        for(int i = 0 ; i < n ; i ++){
    
    
            parent[i] = i;
            sz[i] = 1; // 2. 初始化,每个 sz[i] = 1
        }
    }

    public int find(int p){
    
     // 没有变化... }
    public boolean isConnected(int p , int q){
    
     // 没有变化 }

    public void unionElements(int p, int q){
    
    
        int pRoot = find(p);
        int qRoot = find(q);
        if( pRoot == qRoot )
            return;
        parent[pRoot] = qRoot;
        // 3. 维护 sz:把 qRoot 的集合元素数量加上 pRoot 的集合元素数量
        sz[qRoot] += sz[pRoot];
    }

    // 4. 最后,设计一个接口让用户可以查询到任意一个元素 p 所在的集合的元素个数 
    public int size(int p){
    
    
        return sz[find(p)]; // 使用 p 所在的集合的根节点查找相应的元素个数
    }
}

LeetCode exercise using floodfill + union

695. Maximum area of ​​islands

Guess you like

Origin blog.csdn.net/weixin_43728138/article/details/118993955