-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathRegionsCutBySlashes.kt
103 lines (91 loc) · 2.96 KB
/
RegionsCutBySlashes.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package questions
import _utils.UseCommentAsDocumentation
import utils.shouldBe
private const val LEFT = '/'
private const val RIGHT = '\\'
/**
* An n x n grid is composed of 1 x 1 squares where each 1 x 1 square consists of a '/', '\', or blank space ' '.
* These characters divide the square into contiguous regions.
* Given the grid `grid` represented as a string array, return the number of regions.
* Note that backslash characters are escaped, so a '\' is represented as '\\'.
*
* [Explanation](https://www.youtube.com/watch?v=Wafu5vOxPRE) – [Source](https://leetcode.com/problems/regions-cut-by-slashes/)
*/
@UseCommentAsDocumentation
private fun regionsBySlashes(grid: Array<String>): Int {
val dots = grid.size + 1
// this is basically a union find problem
// if there's a cycle, then add one to the result
val unionFind = UnionFind(dots)
// Connect the borders
for (i in 0 until dots) {
for (j in 0 until dots) {
if (i == 0 || i == dots - 1 || j == 0 || j == dots - 1) {
val cellNo = i * dots + j
if (cellNo != 0)
unionFind.union(0, cellNo)
}
}
}
// the border is a region
var result = 1
for (i in 0..grid.lastIndex) {
val row = grid[i].toCharArray()
for (j in 0..row.lastIndex) {
val isCycle = when (row[j]) {
LEFT -> {
val cellNoTop = (i * dots) + (j + 1)
val cellNoBottom = (i + 1) * dots + (j)
unionFind.union(cellNoTop, cellNoBottom)
}
RIGHT -> {
val cellNoTop = (i * dots) + (j)
val cellNoBottom = (i + 1) * dots + (j + 1)
unionFind.union(cellNoTop, cellNoBottom)
}
else -> {
false
}
}
if (isCycle) {
result++
}
}
}
return result
}
private class UnionFind(n: Int) {
private val parent = Array(n * n) { it }
private val rank = Array(n * n) { 1 }
fun union(x: Int, y: Int): Boolean {
val lx = find(x)
val ly = find(y)
if (lx == ly) {
return true
}
if (rank[lx] == rank[ly]) {
parent[lx] = ly
rank[ly]++
} else if (rank[lx] > rank[ly]) {
parent[ly] = lx
} else if (rank[lx] < rank[ly]) {
parent[lx] = ly
}
return false
}
fun find(x: Int): Int {
if (parent[x] == x) {
return x
}
val temp = find(parent[x])
parent[x] = temp
return temp
}
}
fun main() {
regionsBySlashes(arrayOf(" /", "/ ")) shouldBe 2
regionsBySlashes(arrayOf(" /", " ")) shouldBe 1
regionsBySlashes(arrayOf("\\/", "/\\")) shouldBe 4
regionsBySlashes(arrayOf("/\\", "\\/")) shouldBe 5
regionsBySlashes(arrayOf("//", "/ ")) shouldBe 3
}