LeetCode684 Redundant Conenction

this problem is not a regualr one, but we can see it in graph right away. we are given an array of edges, and that represent a graph, now we are gonna to remove some edges to make the graph into a valid tree. and we have to remove all the removed edges. the given graph is an undirected.
example:
Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given undirected graph will be like this:
1
/
2 - 3

//For each edge (u, v), traverse the graph with a depth-first search to see if we can connect u to v. If we can, then it must be the duplicate edge. and we just need to break the edge of uv, because we know that they must connected in another way
class Solution {
    Set<Integer> seen = new HashSet();
    int MAX_EDGE_VAL = 1000; //due to this time we have no input which shows the total number of nodes, so we assume it is 1000, it's better for us when build graph using List<>[] instead of hashmap, because we can use index as the key.

    public int[] findRedundantConnection(int[][] edges) {
        List<Integer>[] graph = new ArrayList[MAX_EDGE_VAL + 1]; //stores every node's connected node, due to the node are integers, we can use index of array
        for (int i = 0; i <= MAX_EDGE_VAL; i++) {
            graph[i] = new ArrayList();
        }

        for (int[] edge: edges) {
            seen.clear();
            if (!graph[edge[0]].isEmpty() && !graph[edge[1]].isEmpty() &&
                    dfs(graph, edge[0], edge[1])) { //if those two nodes are connected in another way
                return edge; //then we just need to break this edge and everything will be fine
            }
            graph[edge[0]].add(edge[1]);
            graph[edge[1]].add(edge[0]);
        }
        
    }
    public boolean dfs(List<Integer>[] graph, int source, int target) { //this dfs returns whether source and target is connected
        if (!seen.contains(source)) { //if we haven't meet current node before
            seen.add(source);
            if (source == target) return true; //if we find a way
            for (int nei: graph[source]) { //for all its neighbors
                if (dfs(graph, nei, target)) return true; //if any of neighbor of current node can dfs true, then we have a way, as long as we find one way, then its ok
            }
        }
        return false; //if we have aready meet this node then it means we have a cycle
    }
}

the general idea of this solution: we build the graph use List<>[] and for every edge, and in the mean time, we dfs every edge. you can see from the code, we dfs this edge before we put it in the graph. why? because, we need to find a way from edge[0] to edge[1] other than edge[0]-edge[1]. and when we dfs current edge, if we can find that any negihbor of current starting node can dfs all the way to target, then that is a true in dfs. if we find a right edge, we return it immedaiately.

and another way to solve this problem is Union Find. how can we use that? we can simply find the first edge occuring in the graph that is already connected. that is, each time we try to put an edge into the graph, we try to find those two vertices seperatly, and if they are the same root, then this edge are definitely dupliate connected.

posted @ 2020-05-12 09:51  EvanMeetTheWorld  阅读(19)  评论(0)    收藏  举报