Skip to content

Commit 644815c

Browse files
committed
feat: add solutions to lc problem: No.0711
No.0711.Number of Distinct Islands II
1 parent 8f31ada commit 644815c

File tree

7 files changed

+638
-158
lines changed

7 files changed

+638
-158
lines changed

solution/0700-0799/0711.Number of Distinct Islands II/README.md

Lines changed: 231 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,79 +6,62 @@
66

77
<!-- 这里写题目描述 -->
88

9-
<p>给定一个非空01二维数组表示的网格,一个岛屿由四连通(上、下、左、右四个方向)的 <code>1</code> 组成你可以认为网格的四周被海水包围。</p>
9+
<p>给定一个&nbsp;<code>m x n</code>&nbsp;二进制数组表示的网格&nbsp;<code>grid</code> ,一个岛屿由 <strong>四连通</strong> (上、下、左、右四个方向)的 <code>1</code> 组成(代表陆地)。你可以认为网格的四周被海水包围。</p>
1010

11-
<p>请你计算这个网格中共有多少个形状不同的岛屿。如果两个岛屿的形状相同,或者通过旋转(顺时针旋转 90&deg;,180&deg;,270&deg;)、翻转(左右翻转、上下翻转)后形状相同,那么就认为这两个岛屿是相同的。</p>
11+
<p>如果两个岛屿的形状相同,或者通过旋转(顺时针旋转 90°,180°,270°)、翻转(左右翻转、上下翻转)后形状相同,那么就认为这两个岛屿是相同的。</p>
1212

13-
<p>&nbsp;</p>
14-
15-
<p><strong>样例 1:</strong></p>
16-
17-
<pre>11000
18-
10000
19-
00001
20-
00011
21-
</pre>
22-
23-
<p>给定上图,返回结果 <code>1</code>。<br>
24-
<br>
25-
注意 :</p>
26-
27-
<pre>11
28-
1
29-
</pre>
30-
31-
<p>和</p>
32-
33-
<pre> 1
34-
11</pre>
35-
36-
<p>是相同的岛屿。因为我们通过 180&deg; 旋转第一个岛屿,两个岛屿的形状相同。</p>
13+
<p>返回 <em>这个网格中形状 <strong>不同</strong> 的岛屿的数量&nbsp;</em>。</p>
3714

3815
<p>&nbsp;</p>
3916

40-
<p><strong>样例&nbsp;2:</strong></p>
17+
<p><strong>示例 1:</strong></p>
4118

42-
<pre>11100
43-
10001
44-
01001
45-
01110</pre>
19+
<p><img src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/0700-0799/0711.Number%20of%20Distinct%20Islands%20II/images/distinctisland2-1-grid.jpg" style="height: 162px; width: 200px;" /></p>
4620

47-
<p>给定上图,返回结果 <code>2</code>。<br>
48-
<br>
49-
下面是两个不同的岛屿:</p>
21+
<pre>
22+
<strong>输入:</strong> grid = [[1,1,0,0,0],[1,0,0,0,0],[0,0,0,0,1],[0,0,0,1,1]]
23+
<strong>输出:</strong> 1
24+
<strong>解释:</strong> 这两个是相同的岛屿。因为我们通过 180° 旋转第一个岛屿,两个岛屿的形状相同。
25+
</pre>
5026

51-
<pre>111
52-
1</pre>
27+
<p><strong>示例 2:</strong></p>
5328

54-
<p></p>
29+
<p><img alt="" src="https://cdn.jsdelivr.net/gh/doocs/leetcode@main/solution/0700-0799/0711.Number%20of%20Distinct%20Islands%20II/images/distinctisland1-1-grid.jpg" style="height: 162px; width: 200px;" /></p>
5530

56-
<pre>1
57-
1
31+
<pre>
32+
<strong>输入:</strong> grid = [[1,1,0,0,0],[1,1,0,0,0],[0,0,0,1,1],[0,0,0,1,1]]
33+
<strong>输出:</strong> 1
5834
</pre>
5935

6036
<p>&nbsp;</p>
6137

62-
<p>注意 :</p>
63-
64-
<pre>111
65-
1</pre>
38+
<p><strong>提示:</strong></p>
6639

67-
<p>和</p>
40+
<ul>
41+
<li><code>m == grid.length</code></li>
42+
<li><code>n == grid[i].length</code></li>
43+
<li><code>1 &lt;= m, n &lt;= 50</code></li>
44+
<li><code>grid[i][j]</code>&nbsp;不是&nbsp;<code>0</code>&nbsp;就是&nbsp;<code>1</code>.</li>
45+
</ul>
6846

69-
<pre>1
70-
111
71-
</pre>
72-
73-
<p>相同的岛屿。因为我们通过上下翻转第一个岛屿,两个岛屿的形状相同。</p>
47+
## 解法
7448

75-
<p>&nbsp;</p>
49+
<!-- 这里可写通用的实现逻辑 -->
7650

77-
<p><strong>注释 :</strong>&nbsp; 二维数组每维的大小都不会超过50。</p>
51+
先利用 DFS 找出每个岛屿,随后对岛屿进行翻转、旋转等操作,得到以下 8 种不同的情况,并对这些情况进行标准化 `normalize` 处理,得到该岛屿的特征值,放到哈希表中。最后返回哈希表的元素数量即可。
7852

79-
## 解法
53+
```
54+
原坐标: (i, j)
55+
上下翻转: (i, -j)
56+
左右翻转: (-i, j)
57+
90°旋转: (j, -i)
58+
180°旋转: (-i, -j)
59+
270°旋转: (-j, -i)
60+
90°旋转+左右翻转: (-j, -i)
61+
90°旋转+上下翻转: (j, i)
62+
```
8063

81-
<!-- 这里可写通用的实现逻辑 -->
64+
标准化 `normalize` 的思路是:对于岛屿的每一种情况,先按照横、纵坐标升序排列坐标点,得到的第一个点 `(a, b)` 是最小的点,将其化为 `(0, 0)`,对于其他点 `(x, y)`,则化为 `(x - a, y - b)`。然后排序这 8 种情况,获取最小的一种,作为该岛屿的标准化值。
8265

8366
<!-- tabs:start -->
8467

@@ -87,15 +70,209 @@
8770
<!-- 这里可写当前语言的特殊实现逻辑 -->
8871

8972
```python
90-
73+
class Solution:
74+
def numDistinctIslands2(self, grid: List[List[int]]) -> int:
75+
def dfs(i, j, shape):
76+
shape.append([i, j])
77+
grid[i][j] = 0
78+
for a, b in [[1, 0], [-1, 0], [0, 1], [0, -1]]:
79+
x, y = i + a, j + b
80+
if 0 <= x < m and 0 <= y < n and grid[x][y] == 1:
81+
dfs(x, y, shape)
82+
83+
def normalize(shape):
84+
shapes = [[] for _ in range(8)]
85+
for i, j in shape:
86+
shapes[0].append([i, j])
87+
shapes[1].append([i, -j])
88+
shapes[2].append([-i, j])
89+
shapes[3].append([-i, -j])
90+
shapes[4].append([j, i])
91+
shapes[5].append([j, -i])
92+
shapes[6].append([-j, i])
93+
shapes[7].append([-j, -i])
94+
for e in shapes:
95+
e.sort()
96+
for i in range(len(e) - 1, -1, -1):
97+
e[i][0] -= e[0][0]
98+
e[i][1] -= e[0][1]
99+
shapes.sort()
100+
return tuple(tuple(e) for e in shapes[0])
101+
102+
m, n = len(grid), len(grid[0])
103+
s = set()
104+
for i in range(m):
105+
for j in range(n):
106+
if grid[i][j]:
107+
shape = []
108+
dfs(i, j, shape)
109+
s.add(normalize(shape))
110+
return len(s)
91111
```
92112

93113
### **Java**
94114

95115
<!-- 这里可写当前语言的特殊实现逻辑 -->
96116

97117
```java
118+
class Solution {
119+
private int m;
120+
private int n;
121+
private int[][] grid;
122+
123+
public int numDistinctIslands2(int[][] grid) {
124+
m = grid.length;
125+
n = grid[0].length;
126+
this.grid = grid;
127+
Set<List<List<Integer>>> s = new HashSet<>();
128+
for (int i = 0; i < m; ++i) {
129+
for (int j = 0; j < n; ++j) {
130+
if (grid[i][j] == 1) {
131+
List<Integer> shape = new ArrayList<>();
132+
dfs(i, j, shape);
133+
s.add(normalize(shape));
134+
}
135+
}
136+
}
137+
return s.size();
138+
}
139+
140+
private List<List<Integer>> normalize(List<Integer> shape) {
141+
List<int[]>[] shapes = new List[8];
142+
for (int i = 0; i < 8; ++i) {
143+
shapes[i] = new ArrayList<>();
144+
}
145+
for (int e : shape) {
146+
int i = e / n;
147+
int j = e % n;
148+
shapes[0].add(new int[]{i, j});
149+
shapes[1].add(new int[]{i, -j});
150+
shapes[2].add(new int[]{-i, j});
151+
shapes[3].add(new int[]{-i, -j});
152+
shapes[4].add(new int[]{j, i});
153+
shapes[5].add(new int[]{j, -i});
154+
shapes[6].add(new int[]{-j, i});
155+
shapes[7].add(new int[]{-j, -i});
156+
}
157+
for (List<int[]> e : shapes) {
158+
e.sort((a, b) -> {
159+
int i1 = a[0];
160+
int j1 = a[1];
161+
int i2 = b[0];
162+
int j2 = b[1];
163+
if (i1 == i2) {
164+
return j1 - j2;
165+
}
166+
return i1 - i2;
167+
});
168+
int a = e.get(0)[0];
169+
int b = e.get(0)[1];
170+
for (int k = e.size() - 1; k >= 0; --k) {
171+
int i = e.get(k)[0];
172+
int j = e.get(k)[1];
173+
e.set(k, new int[]{i - a, j - b});
174+
}
175+
}
176+
Arrays.sort(shapes, (a, b) -> {
177+
for (int k = 0; k < a.size(); ++k) {
178+
int i1 = a.get(k)[0];
179+
int j1 = a.get(k)[1];
180+
int i2 = b.get(k)[0];
181+
int j2 = b.get(k)[1];
182+
if (i1 != i2) {
183+
return i1 - i2;
184+
}
185+
if (j1 != j2) {
186+
return j1 - j2;
187+
}
188+
}
189+
return 0;
190+
});
191+
List<List<Integer>> ans = new ArrayList<>();
192+
for (int[] e : shapes[0]) {
193+
ans.add(Arrays.asList(e[0], e[1]));
194+
}
195+
return ans;
196+
}
197+
198+
private void dfs(int i, int j, List<Integer> shape) {
199+
shape.add(i * n + j);
200+
grid[i][j] = 0;
201+
int[] dirs = {-1, 0, 1, 0, -1};
202+
for (int k = 0; k < 4; ++k) {
203+
int x = i + dirs[k];
204+
int y = j + dirs[k + 1];
205+
if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1) {
206+
dfs(x, y, shape);
207+
}
208+
}
209+
}
210+
}
211+
```
98212

213+
### **C++**
214+
215+
```cpp
216+
typedef pair<int,int> PII;
217+
218+
class Solution {
219+
public:
220+
int numDistinctIslands2(vector<vector<int>>& grid) {
221+
set<vector<PII>> s;
222+
for (int i = 0; i < grid.size(); ++i)
223+
{
224+
for (int j = 0; j < grid[0].size(); ++j)
225+
{
226+
if (grid[i][j])
227+
{
228+
vector<PII> shape;
229+
dfs(i, j, grid, shape);
230+
s.insert(normalize(shape));
231+
}
232+
}
233+
}
234+
return s.size();
235+
}
236+
237+
vector<PII> normalize(vector<PII>& shape) {
238+
vector<vector<PII>> shapes(8);
239+
for (auto& e : shape)
240+
{
241+
int i = e.first, j = e.second;
242+
shapes[0].push_back({i, j});
243+
shapes[1].push_back({i, -j});
244+
shapes[2].push_back({-i, j});
245+
shapes[3].push_back({-i, -j});
246+
shapes[4].push_back({j, i});
247+
shapes[5].push_back({j, -i});
248+
shapes[6].push_back({-j, -i});
249+
shapes[7].push_back({-j, i});
250+
}
251+
for (auto& e : shapes)
252+
{
253+
sort(e.begin(), e.end());
254+
for (int k = e.size() - 1; k >= 0; --k)
255+
{
256+
e[k].first -= e[0].first;
257+
e[k].second -= e[0].second;
258+
}
259+
}
260+
sort(shapes.begin(), shapes.end());
261+
return shapes[0];
262+
}
263+
264+
void dfs(int i, int j, vector<vector<int>>& grid, vector<PII>& shape) {
265+
shape.push_back({i, j});
266+
grid[i][j] = 0;
267+
vector<int> dirs = {-1, 0, 1, 0, -1};
268+
for (int k = 0; k < 4; ++k)
269+
{
270+
int x = i + dirs[k], y = j + dirs[k + 1];
271+
if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size() && grid[x][y] == 1)
272+
dfs(x, y, grid, shape);
273+
}
274+
}
275+
};
99276
```
100277

101278
### **...**

0 commit comments

Comments
 (0)