-
Notifications
You must be signed in to change notification settings - Fork 93
/
Copy pathRedundantConnectionII685.java
161 lines (147 loc) · 4.73 KB
/
RedundantConnectionII685.java
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**
* In this problem, a rooted tree is a directed graph such that, there is
* exactly one node (the root) for which all other nodes are descendants of
* this node, plus every node has exactly one parent, except for the root
* node which has no parents.
*
* The given input is a directed graph that started as a rooted tree with N
* nodes (with distinct values 1, 2, ..., N), with one additional directed
* edge added. The added edge has two different vertices chosen from 1 to N,
* and was not an edge that already existed.
*
* The resulting graph is given as a 2D-array of edges. Each element of edges
* is a pair [u, v] that represents a directed edge connecting nodes u and v,
* where u is a parent of child v.
*
* Return an edge that can be removed so that the resulting graph is a rooted
* tree of N nodes. If there are multiple answers, return the answer that
* occurs last in the given 2D-array.
*
* Example 1:
* Input: [[1,2], [1,3], [2,3]]
* Output: [2,3]
* Explanation: The given directed graph will be like this:
* 1
* / \
* v v
* 2-->3
*
* Example 2:
* Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
* Output: [4,1]
* Explanation: The given directed graph will be like this:
* 5 <- 1 -> 2
* ^ |
* | v
* 4 <- 3
*
* Note:
* The size of the input 2D-array will be between 3 and 1000.
* Every integer represented in the 2D-array will be between 1 and N,
* where N is the size of the input array.
*/
public class RedundantConnectionII685 {
public int[] findRedundantDirectedConnection(int[][] edges) {
int N = edges.length;
int[] res1 = null;
int[] res2 = null;
int[] parent = new int[N+1];
boolean twoParentsExist = false;
for (int[] edge: edges) {
int u = edge[0];
int v = edge[1];
if (parent[v] != 0) {
res1 = new int[]{parent[v], v};
res2 = new int[]{u, v};
twoParentsExist = true;
break;
}
parent[v] = u;
}
DisjointSet djs = new DisjointSet(N);
for (int[] edge: edges) {
int u = edge[0];
int v = edge[1];
if (twoParentsExist && ((u == res1[0] && v == res1[1]) || (u == res2[0] && v == res2[1]))) continue;
int up = djs.find(u);
int vp = djs.find(v);
if (up == vp) {
return edge;
} else {
djs.union(u, v);
}
}
if (twoParentsExist && djs.find(res1[0]) == djs.find(res1[1])) {
return res1;
}
return res2;
}
class DisjointSet {
int[] parent;
int[] rank;
DisjointSet(int N) {
parent = new int[N+1];
for (int i=0; i<N; i++) parent[i] = i;
rank = new int[N+1];
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
void union(int x, int y) {
int xp = find(x);
int yp = find(y);
if (rank[xp] > rank[yp]) {
parent[yp] = xp;
} else if (rank[xp] < rank[yp]) {
parent[xp] = yp;
} else {
parent[xp] = yp;
rank[yp]++;
}
}
}
/**
* https://leetcode.com/problems/redundant-connection-ii/discuss/108045/C++Java-Union-Find-with-explanation-O(n)
*/
public int[] findRedundantDirectedConnection2(int[][] edges) {
int[] can1 = {-1, -1};
int[] can2 = {-1, -1};
int[] parent = new int[edges.length + 1];
for (int i = 0; i < edges.length; i++) {
if (parent[edges[i][1]] == 0) {
parent[edges[i][1]] = edges[i][0];
} else {
can2 = new int[] {edges[i][0], edges[i][1]};
can1 = new int[] {parent[edges[i][1]], edges[i][1]};
edges[i][1] = 0;
}
}
for (int i = 0; i < edges.length; i++) {
parent[i] = i;
}
for (int i = 0; i < edges.length; i++) {
if (edges[i][1] == 0) {
continue;
}
int child = edges[i][1], father = edges[i][0];
if (root(parent, father) == child) {
if (can1[0] == -1) {
return edges[i];
}
return can1;
}
parent[child] = father;
}
return can2;
}
int root(int[] parent, int i) {
while (i != parent[i]) {
parent[i] = parent[parent[i]];
i = parent[i];
}
return i;
}
}