图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II

Posted hyserendipity

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II相关的知识,希望对你有一定的参考价值。

2020-04-04 18:25:18

问题描述:

给定一个01的非空的二维数组网格,一个岛是一个1(表示陆地)的组,4个方向(水平或垂直)连接。你可以假设网格的所有四条边都被水包围。
计算不同岛屿的数量。当一个岛被认为与另一个岛相同时,它们有相同的形状,或在旋转后的形状相同(90,180,或270度)或翻转(左/右方向或向上/向下方向)。

样例

Example 1:

Input: [[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]
Output: 1
Explanation:
The island is look like this:
11000
10000
00001
00011

Notice that:
11
1
and
 1
11
are considered same island shapes. Because if we make a 180 degrees clockwise rotation on the first island, then two islands will have the same shapes.

Example 2:

Input: [[1,1,1,0,0],[1,0,0,0,1],[0,1,0,0,1],[0,1,1,1,0]]
Output: 2
Explanation:
The island is look like this:
11100
10001
01001
01110

Here are the two distinct islands:
111
1
and
1
1

Notice that:
111
1
and
1
111
are considered same island shapes. Because if we flip the first array in the up/down direction, then they have the same shapes.

注意事项

每个维度在给定网格的长度不超过50

问题求解:

 

    public int numDistinctIslands2(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        int m = grid.length, n = grid[0].length;
        Set<String> res = new HashSet<>();
        
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1) {
                    List<int[]> island = new ArrayList<>();
                    dfs(grid, i, j, island);
                    res.add(getUnique(island));
                }
            }
        }
        
        return res.size();
    }
    
    private void dfs(int[][]grid, int x, int y, List<int[]> island) {
        int m = grid.length, n = grid[0].length;
        
        island.add(new int[]{x, y});
        grid[x][y] = 0;
        
        int[] dirs = {-1, 0, 1, 0, -1};
        for (int i = 0; i < 4; ++i) {
            int nx = x + dirs[i];
            int ny = y + dirs[i + 1];
            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 1) {
                dfs(grid, nx, ny, island);
            }
        }
    }
    
    private String getUnique(List<int[]> island) {
        List<String> sameIslands = new ArrayList<>();
        
        int[][] trans={{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
        
        for (int i = 0; i < 4; ++i) {
            List<int[]> l1 = new ArrayList<>(), l2 = new ArrayList<>();
            
            for (int[] is : island) {
                int x = is[0], y = is[1];
                l1.add(new int[]{x * trans[i][0], y * trans[i][1]});
                l2.add(new int[]{y * trans[i][0], x * trans[i][1]});
            }
            sameIslands.add(getStr(l1));
            sameIslands.add(getStr(l2));
        }
        
        Collections.sort(sameIslands);
        return sameIslands.get(0);
    }
    
    private String getStr(List<int[]> island) {
        
        Collections.sort(island, (int[] o1, int[] o2) -> o1[0] == o2[0] ? Integer.compare(o1[1], o2[1]) : Integer.compare(o1[0], o2[0]));
        
        StringBuilder sb = new StringBuilder();
        int x = island.get(0)[0], y = island.get(0)[1];
        
        for (int[] point : island) {
            sb.append((point[0] - x) + " " + (point[1] - y) + " ");
        }
        return sb.toString();
    }

  

以上是关于图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 200 岛屿数量[DFS] HERODING的LeetCode之路

DFS的运用(二分图判定无向图的割顶和桥,双连通分量,有向图的强连通分量)

寻找图的强连通分量:tarjan算法简单理解

连通图基本知识

图的遍历——A1013Battle over cities(25) 求需要添加多少条边才能构成连通图转化为找连通分量(可由DFS 和 并查集来找连通分量)

强连通分量