Skip to content

Commit d5309db

Browse files
[N-0] add 694
1 parent 73c2a0f commit d5309db

File tree

3 files changed

+255
-0
lines changed

3 files changed

+255
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Your ideas/fixes/algorithms are more than welcome!
2323
| # | Title | Solutions | Time | Space | Difficulty | Tag | Notes
2424
|-----|----------------|---------------|---------------|---------------|-------------|--------------|-----
2525
|695|[Max Area of Island](https://leetcode.com/problems/max-area-of-island/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_695.java) | O(m*n) | O(1) | Easy | DFS
26+
|694|[Number of Distinct Islands](https://leetcode.com/problems/number-of-distinct-islands/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_694.java) | O(m*n) | O(1) | Medium | DFS
2627
|693|[Binary Number with Alternating Bits](https://leetcode.com/problems/binary-number-with-alternating-bits/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_693.java) | O(n) | O(1) | Easy |
2728
|690|[Employee Importance](https://leetcode.com/problems/employee-importance/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_690.java) | O(n) | O(h) | Easy | DFS
2829
|688|[Knight Probability in Chessboard](https://leetcode.com/problems/knight-probability-in-chessboard/)|[Solution](../master/src/main/java/com/fishercoder/solutions/_688.java) | O(n^2) | O(n^2) | Medium | DP
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
package com.fishercoder.solutions;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Set;
8+
9+
/**
10+
* 694. Number of Distinct Islands
11+
*
12+
* Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land)
13+
* connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
14+
* Count the number of distinct islands.
15+
* An island is considered to be the same as another if and only if
16+
* one island can be translated (and not rotated or reflected) to equal the other.
17+
18+
Example 1:
19+
20+
11000
21+
11000
22+
00011
23+
00011
24+
25+
Given the above grid map, return 1.
26+
27+
Example 2:
28+
29+
11011
30+
10000
31+
00001
32+
11011
33+
34+
Given the above grid map, return 3.
35+
36+
Notice that:
37+
38+
11
39+
1
40+
41+
and
42+
43+
1
44+
11
45+
46+
are considered different island shapes, because we do not consider reflection / rotation.
47+
48+
Note: The length of each dimension in the given grid does not exceed 50.
49+
*/
50+
public class _694 {
51+
public static class Solution1 {
52+
/**
53+
* My original idea:
54+
* my not fully working yet: the equals() and hashcode() methods need to be refined
55+
* because HashSet is not really filtering the islands wiht the same shape.
56+
*/
57+
class Quadrilateral {
58+
int[] topLeft;
59+
int[] bottomLeft;
60+
int[] topRight;
61+
int[] bottomRight;
62+
int area;
63+
64+
public Quadrilateral(int i, int j) {
65+
this.area = 0;
66+
this.topLeft = new int[]{i, j};
67+
this.topRight = new int[]{i, j};
68+
this.bottomLeft = new int[]{i, j};
69+
this.bottomRight = new int[]{i, j};
70+
}
71+
72+
@Override
73+
public boolean equals(Object o) {
74+
if (this == o) return true;
75+
if (!(o instanceof Quadrilateral)) return false;
76+
77+
Quadrilateral that = (Quadrilateral) o;
78+
return this.area == that.area && checkDistance(that);
79+
}
80+
81+
private boolean checkDistance(Quadrilateral that) {
82+
int thisTop = computeDistance(this.topLeft, this.topRight);
83+
int thatTop = computeDistance(that.topLeft, that.topRight);
84+
if (thisTop != thatTop) {
85+
return false;
86+
}
87+
int thisRight = computeDistance(this.topRight, this.bottomRight);
88+
int thatRight = computeDistance(that.topRight, that.bottomRight);
89+
if (thisRight != thatRight) {
90+
return false;
91+
}
92+
int thisBottom = computeDistance(this.bottomRight, this.bottomLeft);
93+
int thatBottom = computeDistance(that.bottomRight, that.bottomLeft);
94+
if (thisBottom != thatBottom) {
95+
return false;
96+
}
97+
int thisLeft = computeDistance(this.bottomLeft, this.topLeft);
98+
int thatLeft = computeDistance(that.bottomLeft, that.topLeft);
99+
return thisLeft == thatLeft;
100+
}
101+
102+
private int computeDistance(int[] A, int[] B) {
103+
return (int) (Math.pow(A[0] - B[0], 2) + Math.pow(A[1] - B[1], 2));
104+
}
105+
106+
@Override
107+
public int hashCode() {
108+
return area + computeDistance(this.topLeft, this.topRight) + computeDistance(this.topRight, this.bottomRight)
109+
+ computeDistance(this.bottomRight, this.bottomLeft) + computeDistance(this.bottomLeft, this.topLeft);
110+
}
111+
112+
public void addPoint(int i, int j) {
113+
//todo: check wether this point (i,j) is in the range, if not, expand the range
114+
if (i == topRight[0]) {
115+
topRight[1] = Math.max(topRight[1], j);
116+
}
117+
if (j == topRight[1]) {
118+
topRight[0] = Math.min(topRight[1], i);
119+
}
120+
if (i == topLeft[0]) {
121+
topLeft[1] = Math.min(topLeft[1], j);
122+
}
123+
if (j == topLeft[1]) {
124+
topLeft[0] = Math.min(topLeft[0], i);
125+
}
126+
if (i == bottomLeft[0]) {
127+
bottomLeft[1] = Math.min(bottomLeft[1], j);
128+
}
129+
if (j == bottomLeft[1]) {
130+
bottomLeft[0] = Math.max(bottomLeft[0], i);
131+
}
132+
if (j == bottomRight[1]) {
133+
bottomRight[0] = Math.max(bottomRight[0], i);
134+
}
135+
if (i == bottomRight[0]) {
136+
bottomRight[1] = Math.max(bottomRight[1], j);
137+
}
138+
}
139+
140+
public void addArea() {
141+
this.area++;
142+
}
143+
}
144+
145+
public int numDistinctIslands(int[][] grid) {
146+
Set<Quadrilateral> set = new HashSet<>();
147+
int m = grid.length;
148+
int n = grid[0].length;
149+
for (int i = 0; i < m; i++) {
150+
for (int j = 0; j < n; j++) {
151+
if (grid[i][j] == 1) {
152+
Quadrilateral quadrilateral = dfs(grid, i, j, m, n, new Quadrilateral(i, j));
153+
set.add(quadrilateral);
154+
}
155+
}
156+
}
157+
return set.size();
158+
}
159+
160+
private Quadrilateral dfs(int[][] grid, int i, int j, int m, int n, Quadrilateral quadrilateral) {
161+
if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 0) {
162+
return quadrilateral;
163+
}
164+
grid[i][j] = 0;
165+
quadrilateral.addPoint(i, j);
166+
quadrilateral.addArea();
167+
quadrilateral = dfs(grid, i + 1, j, m, n, quadrilateral);
168+
quadrilateral = dfs(grid, i - 1, j, m, n, quadrilateral);
169+
quadrilateral = dfs(grid, i, j + 1, m, n, quadrilateral);
170+
quadrilateral = dfs(grid, i, j - 1, m, n, quadrilateral);
171+
return quadrilateral;
172+
}
173+
}
174+
175+
public static class Solution2 {
176+
int[][] directions = new int[][]{
177+
{0, 1},
178+
{1, 0},
179+
{0, -1},
180+
{-1, 0}
181+
};
182+
183+
public int numDistinctIslands(int[][] grid) {
184+
int m = grid.length;
185+
int n = grid[0].length;
186+
Set<List<List<Integer>>> uniqueShapeIslands = new HashSet<>();
187+
for (int i = 0; i < m; i++) {
188+
for (int j = 0; j < n; j++) {
189+
List<List<Integer>> island = new ArrayList<>();
190+
if (dfs(i, j, i, j, grid, m, n, island)) {
191+
uniqueShapeIslands.add(island);
192+
}
193+
}
194+
}
195+
return uniqueShapeIslands.size();
196+
}
197+
198+
private boolean dfs(int i0, int j0, int i, int j
199+
, int[][] grid, int m, int n, List<List<Integer>> island) {
200+
if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] <= 0) {
201+
return false;
202+
}
203+
island.add(Arrays.asList(i - i0, j - j0));
204+
grid[i][j] *= -1;
205+
for (int k = 0; k < 4; k++) {
206+
dfs(i0, j0, i + directions[k][0], j + directions[k][1], grid, m, n, island);
207+
}
208+
return true;
209+
}
210+
}
211+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.fishercoder;
2+
3+
import com.fishercoder.solutions._694;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
7+
import static junit.framework.TestCase.assertEquals;
8+
9+
public class _694Test {
10+
private static _694.Solution1 solution1;
11+
private static _694.Solution2 solution2;
12+
private static int[][] grid;
13+
14+
@Before
15+
public void setup() {
16+
solution1 = new _694.Solution1();
17+
solution2 = new _694.Solution2();
18+
}
19+
20+
@Test
21+
public void test1() {
22+
grid = new int[][]{
23+
{1, 1, 0, 1, 1},
24+
{1, 0, 0, 0, 0},
25+
{0, 0, 0, 0, 1},
26+
{1, 1, 0, 1, 1}
27+
};
28+
// assertEquals(3, solution1.numDistinctIslands(grid));
29+
assertEquals(3, solution2.numDistinctIslands(grid));
30+
}
31+
32+
@Test
33+
public void test2() {
34+
grid = new int[][]{
35+
{1, 1, 0, 0, 0},
36+
{1, 1, 0, 0, 0},
37+
{0, 0, 0, 1, 1},
38+
{0, 0, 0, 1, 1}
39+
};
40+
// assertEquals(1, solution1.numDistinctIslands(grid));
41+
assertEquals(1, solution2.numDistinctIslands(grid));
42+
}
43+
}

0 commit comments

Comments
 (0)