Question 5 Redundant Connection
Require: 接下来的题目都要学会用union find实现,还有时间可以尝试用dfs
Method 1:
这是一个无向图,tree里面是不能有环的,多一条其实意思就是有环,方法很暴力
dfs找到这个环,把环上的所有边都要找出来,找到这些边里出现在edge list里的最后一条边
private static final int UNIVISITED = 0;
private static final int VISITING = 1;
private static final int VISITED = 2;
public int[] findRedundantConnection(int[][] edges) {
if (edges == null. || edges.length == 0) {
return new int[]{-1, -1};
}
int[] visited = new int[edges.length + 1]; //off 1?
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i <= edges.length; i++) {
graph.add(new ArrayList<>());
}
for (int[] edge: edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
Set<List<Integer>> cycle = new HashSet<>();
List<Integer> curPath = new ArrayList<>();
DFS(-1, 1, graph, cycle, curPath);
for (int i = edges.length - 1; i >= 0; i--) { //确保是环的后面的可以return
if (cycle.contains(Arrays.asList(eges[i][0], edges[i][1]))) {
return edges[i];
}
}
return edges[edges.length - 1];
}
private boolean DFS(int preNode, int curNode, List<List<Integer>> graph, int[] visited
, Set<List<Integer>> cycle. List<Integer> path) {
if (visited[curNode] == VISITING) {
path.add(curNode);
processCycle(path, cycle, curNode);
path.remove(path.size() - 1);
return true;
}
if (visited[curNode] == VISITED) {
return false;
}
path.add(curNode);
visited[curNode] = VISITING;
for (int nei: graph.get(curNode)) {
if (nei != preNode) && DFS(curNode, nei, graph, visited, cycle, path)) {
//第一个条件是,自己跟自己cycle?
return true;
}
}
visited[curNode] = VISITED;
path.remove(path.size() - 1);
return false;
}
private void precessCylce(List<Integer> path, Set<List<Integer>> cycle, int startPoint) {
// path: 5 -1-2-3-4-1 (start)
int i = path.size() -2;
while (i >= 0 && path.get(i) = startPoint) {
int start = path.get(i);
int end = path.get(i + 1);
List<Integer> temp = new ArrayList<>();
temp.add(start);
temp.add(end);
// 小心是不是要sort: coleection.sort(temp),因为要小心2-3,3-2是一条边
Collections.sort(temp); // O(2log2) = O(1)
cycle.add(temp);
i--;
}
// post processing
List<Integer> temp = new ArrayList<>();
temp.add(start);
temp.add(end);
Collections.sort(temp); // O(2log2) = O(1)
cycle.add(temp);
}
Method 2: Union Find
union:给你的图上两个点相连
find:看看这两个点是不是同一个联通分量
union find怎么知道图中有环?
普通的union相当于把两个点中间连上一条边,如果已经联通的两个点再union
public int[] findRedundantConnection(int[][] edges) {
if (edges == null || edges.length == 0) {
return new int{-1, -1};
}
int[] laoda = new int[edges.length + 1];
int[] size = new int[edges.length + 1];
for (int i = 0; i <= edge.length; i++) {
laoda[i] = i;
size[i] = 1;
}
for (int[] edge: edges) {
int alaoda = find(edge[0], laoda);
int blaoda = find(edge[1], laoda);
if(alaoda == blaoda) {
return edge;
}
}
if (size[alaoda] >= size[blaoda]) {
laoda[blaoda] = alaoda;
size[alaoda] += size[blaoda];
} else {
laoda[alaoda] = blaoda;
size[blaoda] += size[alaoda];
}
return new int[0];
}
private int find(int a, int[] laoda) {
return laoda[a] = laoda[a] == a? a: find(laoda[a], laoda);
}
Last updated