图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II
Posted hyserendipity
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图-dfs-连通分量-旋转变换-804. 不同岛屿的数量II相关的知识,希望对你有一定的参考价值。
2020-04-04 18:25:18
问题描述:
给定一个0
和1
的非空的二维数组网格
,一个岛是一个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的运用(二分图判定无向图的割顶和桥,双连通分量,有向图的强连通分量)
图的遍历——A1013Battle over cities(25) 求需要添加多少条边才能构成连通图转化为找连通分量(可由DFS 和 并查集来找连通分量)