forked from dylansun/leetcode-cn-scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNo685.scala
executable file
·67 lines (57 loc) · 1.8 KB
/
No685.scala
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
object No685 {
def findRedundantDirectedConnection(edges: Array[Array[Int]]): Array[Int] = {
val length = edges.length
val parent1 = (0 to length).toArray
val parent2 = (0 to length).toArray
var _child = 0 // an child has two parent
for (i <- 0 until length)
edges(i) match {
case Array(p, q) =>
if (parent1(q) != q) { // if q already has a parent
parent2(q) = p
_child = q
} else {
parent1(q) = p
parent2(q) = p
}
}
@annotation.tailrec
def hasLoop(parent: Array[Int], i: Int): Boolean =
if (parent(i) == i) false
else if (parent(i) == _child) true
else hasLoop(parent, parent(i))
/**
* if we call this method, there is definitely a cycle and our job is find this cycle.
* We use union find. If two vertex are already connected, the connection between they
* are redundant
*/
def findRedundantDirectedConnection(): Array[Int] = {
val parent = (0 to length).toArray
@annotation.tailrec
def root(p: Int): Int =
if (parent(p) != p) {
parent(p) = parent(parent(p))
root(parent(p))
} else p
def connected(p: Int, q: Int) = root(p) == root(q)
def union(p: Int, q: Int): Unit = {
val rootP = root(p)
val rootQ = root(q)
parent(rootQ) = rootP
}
@annotation.tailrec
def loop(i: Int): Array[Int] = edges(i) match {
case Array(p, q) =>
if (connected(p, q)) edges(i)
else {
union(p, q)
loop(i + 1)
}
}
loop(0)
}
if (hasLoop(parent1, _child)) Array(parent1(_child), _child)
else if (_child != 0) Array(parent2(_child), _child)
else findRedundantDirectedConnection()
}
}